• @Todd M,

    I know this is old but to do what you're looking for, use PSLoggedOn.exe from SysInternals (a Microsoft Tool).

    running the command,

    psloggedon PCName

    will return something like:

    PsLoggedon v1.35 - See who's logged on

    Copyright (C) 2000-2016 Mark Russinovich
    Sysinternals - http://www.sysinternals.com

    Users logged on locally:
         11/20/2019 2:50:27 PM      domainusername

    Users logged on via resource shares:
         11/20/2019 4:09:13 PM      domainyourownusername

  • Guys does someone know why a module (PM1) works in ISE but not in the PS Console.

    Its a little script what I wrote to logon on 365 what write the credentials in the registry.

    Don't get error messages.

    Strange thing is that the same script works within the console when I save it as PS1.

    So not working as PM1 but as PS1 no problem. 

  • I use the following code to install Fonts on remote PCs, no need to logoff or reboot. Tested on 1909.

    #Computers to install fonts to
    $ComputerArray = @("Pc1","Pc2","Pc3")
    #A Share containing only the fonts you want to install
    #Wil be created on remote Pc if not exists, fonts will be copied here and deleted after install.
    foreach ($pc in $ComputerArray) {
    If((Test-Connection -ComputerName  $pc -Count  1 -ErrorAction SilentlyContinue) -and ($Winrmstatus=Test-WSMan -ComputerName $pc -ErrorAction SilentlyContinue)) {
    $RemotePcStagingDir = "$pc$($PcStagingDir.replace(':','$'))"
    $ServiceName = @("WinRM")
    foreach ($svc in $ServiceName) {
            while(((Get-Service -ComputerName $pc -Name $svc -ErrorAction SilentlyContinue).status -ne "Running")-and($i -lt 10)){
                if((Get-Service -ComputerName $pc -Name $svc -ErrorAction SilentlyContinue).StartType -eq "Disabled"){
                Write-Host "Try $i , Setting service $svc StartType to Manual on $pc ..."
                Set-Service -ComputerName $pc -Name $svc -StartupType Manual -ErrorAction SilentlyContinue}
            Write-Host "Try $i / 10 , Starting $svc Service on $pc ..."
            $commandz="sc "+$pc +" Start "+$svc
            & cmd.exe /c $commandz | Out-Null
            sleep 3}
            if($i -ge 10){break}
    if($i -ge 10){Write-Host "Could NOT start service $svc, Skipping Computer $pc" -ForegroundColor Red}else{
    if ( -not (Test-Path -Path $RemotePcStagingDir)){New-Item -Path $RemotePcStagingDir -ItemType Directory -Force}
    $RemoteWinDir=Invoke-Command -ComputerName $pc -ScriptBlock {return $env:windir}
    foreach($FontFile in (Get-ChildItem -file -path $FontDir)){
        if(-not(Test-Path "$pc$($RemoteWinDir.replace(':','$'))Fonts$FontFile")){
            Copy-Item "$FontDir$FontFile" -Destination $RemotePcStagingDir -Force
            Invoke-Command -ComputerName $pc -ScriptBlock {
           $fontRegistryPath = "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionFonts"
           $fontsFolderPath = "$($env:windir)fonts"
        # Create hashtable containing valid font file extensions and text to append to Registry entry name.
        $hashFontFileTypes = @{}
        $hashFontFileTypes.Add(".fon", "")
        $hashFontFileTypes.Add(".fnt", "")
        $hashFontFileTypes.Add(".ttf", " (TrueType)")
        $hashFontFileTypes.Add(".ttc", " (TrueType)")
        $hashFontFileTypes.Add(".otf", " (OpenType)")
            [string]$filePath = (Get-Item $filePath).FullName
            [string]$fileDir  = split-path $filePath
            [string]$fileName = split-path $filePath -leaf
            [string]$fileExt = (Get-Item $filePath).extension
            [string]$fileBaseName = $fileName -replace($fileExt ,"")
            $shell = new-object -com shell.application
            $myFolder = $shell.Namespace($fileDir)
            $fileobj = $myFolder.Items().Item($fileName)
            $fontName = $myFolder.GetDetailsOf($fileobj,21)
            if ($fontName -eq "") { $fontName = $fileBaseName }
            copy-item $filePath -destination $fontsFolderPath
            $fontFinalPath = Join-Path $fontsFolderPath $fileName
            if (-not($hashFontFileTypes.ContainsKey($fileExt))){Write-Host "File Extension Unsupported";$retVal = 0}
            if ($retVal -eq 0) {
                Write-Host "Font `'$($filePath)`'`' installation failed on $env:computername" -ForegroundColor Red
                Write-Host ""
                Set-ItemProperty -path "$($fontRegistryPath)" -name "$($fontName)$($hashFontFileTypes.$fileExt)" -value "$($fileName)" -type STRING
                Write-Host "Font `'$($filePath)`' $fontName $($hashFontFileTypes.$fileExt) installed successfully on $env:computername" -ForegroundColor Green
            Write-Host "An error occured installing `'$($filePath)`' on $env:computername" -ForegroundColor Red
            Write-Host "$($error[0].ToString())" -ForegroundColor Red
         Remove-Item "$RemotePcStagingDir$FontFile" -ErrorAction SilentlyContinue
    foreach($DisabledSvc in $DisabledSvcs){
        Write-Host "Setting service $DisabledSvc StartType to Disabled on $pc ..."
        Set-Service -ComputerName $pc -Name $DisabledSvc -StartupType Disabled -ErrorAction SilentlyContinue
        $commandz="sc "+$pc +" Stop "+$DisabledSvc
        & cmd.exe /c $commandz | Out-Null
    }else{if($Winrmstatus){Write-Host "No Connection to Remote Pc $pc" -ForegroundColor Red}Else{Write-Host "No Connection to WinRM service on Remote Pc $pc" -ForegroundColor Red}}
  • here is an example for creating custom role

    $role = [Microsoft.Azure.Commands.Resources.Models.Authorization.PSRoleDefinition]::new()$role.Name = 'custom access role'$role.Description = 'custom role.'$role.IsCustom = $true$perms = 'Microsoft.Network/networkInterfaces/read','Microsoft.Compute/virtualMachines/read'$role.Actions = $perms$subs = '/subscriptions/hjhjhjhjhjhjhjhjh'$role.AssignableScopes = $subsNew-AzRoleDefinition -Role $role

  • Hi Swapnil,

    Thank you for the reply.

    Sure i will try to create a custom role using the link provided by you.

    But i'm looking for some help in creating a powershell script to make this role assignment in an automated way via Azure DevOps.

    If any one can help me in creating a script or a sample script where we can use these things will really help me.

    Thanks & Regards,


  • Dear Venkat, you may create custom role with permissions defined in 'Microsoft.Databricks' section of document https://docs.microsoft.com/en-us/azure/role-based-access-control/resource-provider-operations.

    Then assign that role to user. 

  • The company I'm working for has a GPO which maps drives for users who are members of certain groups to letters and paths. We're converting these GPOs to a new system which dynamically maps users using a logon script which looks for users in groups with a standard naming convention and in a certain OU and maps them to the path in the group description field. The migration process sometimes has errors, and I'd like to write a script to double check the process used by another group. I saw a posting by Tobias Weltner which looked like it would be a good start:

    $Xml.Machines.Machine | Where-Object { $_.Name -eq 'Server0009' } | Select-Object -Property IP, {$_.Information.info1}

    What I'm trying to do is look in every

    $GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive node and pull every

    where the $GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive.filters.filtergroup.name -matches a group name entered in read-host or a gui menu.

    Everything I've tried results in ALL of the paths, letters, or group names being returned, not just the ones associated with the group name entered.


    $GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive | ? {$GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive.filters.filtergroup.name -match "EU_Country_drivemap_GPO"} | select ($GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive.properties).path


    $GPO_report_drives = $GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive
    foreach ($GPO_report_drive in $GPO_report_drives)
    if ($GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive.filters.filtergroup.name -match "EU_Country_drivemap_GPO")

    Below is an example of one drive node:

    q1:Drive clsid="{935D1B74-9CB8-4e3c-9914-7DD559B7A417}" name="P:" status="P:" image="2" changed="2011-06-21 15:32:03" uid="{3BCD4228-1598-45BE-A994-DF073740B745}" userContext="1" bypassErrors="1">
    <q1:Properties action="U" thisDrive="NOCHANGE" allDrives="NOCHANGE" userName="" path="servernamePublic" label="Country PUBLIC" persistent="1" useLetter="1" letter="P" />
    <q1:FilterGroup bool="AND" not="0" name="DomainEU_Country_drivemap_GPO" sid="S-1-5-21-1417001333-790525478-839522115-749829" userContext="1" primaryGroup="0" localGroup="0" />

    I'm trying to produce output like: Groupname   Driveletter   Path

    for every drive letter and path for each group.

    I'll keep trying, but if someone has a solution or can point me in the right direction, I'd appreciate it.

    I know about select-xml, but have had less luck trying to use it.

  • Hi,

    thanks for this very helpful article. I used an immediate scheduled task to deploy a task with a powershell script which personalizes the template paths of Office 2013 for our users. The task runs in the user's context to be able to write to HKCU. It all worked well but every time the policy was pulled, the script window popped up and flashed for a second for every user, every 90 minutes. I tried “powershell.exe -WindowStyle Hidden”, “| Out-Null”, “>$nul 2&>1” and the task's hidden flag but none worked.

    Reason is that powershell.exe has a parameter -WindowStyle with a possible value Hidden which obviously doesn’t work as expected / is broken. The official issue: https://github.com/PowerShell/PowerShell/issues/3028

    The workaround I found while reading the Github thread is:

    Set objShell = CreateObject("Wscript.Shell")
    Set args = Wscript.Arguments
    For Each arg In args
    	objShell.Run("powershell -windowstyle hidden -executionpolicy bypass -noninteractive ""&"" ""'" & arg & "'"""),0

    … and then call the powershell script you want to execute like this:

    wscript "C:PathTops-run.vbs" "C:OtherPathToyour-script.ps1"

    Now I can run my script using the immediate scheduled task in my GPO without disturbing any user and config their session settings. Yay! Tested with Win10 x64 Build 1809, Win7 x86, Win7 x64.


  • Hi Baki,

    Is there any way we can assign permissions per service? Example, if i want to assign a role for a specific user to have access only to either DataBricks/ADLSV2 like that.

  • Is it possible to list the date when each profile was created?

    I need a script that will identify profiles that were created after a certain date so that I can then remove them.

    (For OS rollback)

  • This is an awesome add on. I'm testing it now to see how it compares to sapien powershell studio.

  • You have to remove the last backslash. This works:

    tree $p
  • "If we use WhatIf when calling this function, this method will return $true." Isn't the opposite true? Using WhatIf should prevent the critical block from executing.

  • Brilliant and oh so helpful!  Thank you!

    One question:  When using the GUI, one can add a custom permission for the Private Key.  While I can do this after the key is installed, is there a way to add READ permission for "mydomainNETWORK SERVICE" account in the request?

  • Sorry about the confusion.

    Registry does not give you an environmental variable but a complete path as I have shown below. I was using that environmental variable as as an example. Let me explain my code and logic.

    1. Registry is one of the options to explore applications in a code. There are 2 locations:

    • 64bit: HKLM:SOFTWAREMicrosoftWindowsCurrentVersionUninstall
    • 32 bit: HKLM:SoftwareWow6432NodeMicrosoftWindowsCurrentVersionUninstall

    2. Below is an example of Adobe Acrobat that uses 32 bit.

    (Sorry Wordfence won't let me share the script in the script mode.)

    $appString6432 = '*acro*' # assume you have adobe acrobat on the computer or replace it with any other app
    $reg6432 = 'HKLM:SoftwareWow6432NodeMicrosoftWindowsCurrentVersionUninstall*'
    $app6432 = Get-ItemProperty $reg6432 | Where-Object {$_.DisplayName -like $appString6432}

    $InstallLocation = $app6432.InstallLocation

    Running on the PS terminal:

    C:UsersRatan> $InstallLocation
    C:Program Files (x86)AdobeAcrobat Reader DC C:UsersRatan> tree $InstallLocation
    Folder PATH listing for volume Windows
    Volume serial number is 2E3F-D6FD
    No subfolders exist

    So, the code gives you a variable $InstallLocation with a value of C:PROGRAM FILES (X86)ADOBEACROBAT READER DC . When you process that variable you get an error. Something is missing in my understanding of PS variables!

  • Yeah I saw that. But where are you using the environment variable for the programs folder? Can you describe what exactly your problem is? You can't assume that everyone knows how Adobe stores its data in the Registry.

  • as I mentioned earlier

    $appString6432 = '*acro*'     # assume you have adobe acrobat on the computer or replace it with any other app
    $reg6432 = 'HKLM:SoftwareWow6432NodeMicrosoftWindowsCurrentVersionUninstall*'
    $app6432 = Get-ItemProperty $reg6432 | Where-Object {$_.DisplayName -like $appString6432}
    $InstallLocation= $app6432.InstallLocation
    tree $InstallLocation
  • I am sorry, I can't follow. Which code does not work?

  • Load More