#StackBounty: #powershell #bcdedit Programmatically restart computer and boot into flash drive

Bounty: 50

I originally posted this on StackOverflow but was told that this may be a better place to post this question, so here goes;

I’ve created a small script which will automatically reboot a computer into it’s recoverysequence (Windows Troubleshoot), which works. Here is my code:

$testpath = test-path "bcdedit.txt"
if ($testpath -eq $true){
    Remove-item "bcdedit.txt"
}
bcdedit | Out-File "bcdedit.txt"
foreach($line in Get-Content .bcdedit.txt) {
    if($line -match $regex){
        if($line -like 'recoverysequence*') {
            $variable = "{" + $line.Split('{')[-1]
        }
    }
}
bcdedit /bootsequence $variable
Remove-item "bcdedit.txt"
shutdown /r /t 1

This powershell script is ran from my Electron (nodejs) application, which is basically an application that is ran on hundreds of different computer models per day, which gathers hardware information and compares it to a database to retrieve the units UPC in a production environment.

However, I have this feature because I couldn’t figure out a way to do what I really wanted to do. I wanted this script to actually reboot a computer, and boot into a plugged in USB drives .EFI file. Rebooting to Windows Troubleshooting was a workaround that I implemented because inside of this troubleshooting environment users have a button that they can press that allows them to choose an external drive to boot into – I’m posting here because I would really like to eliminate this step and just boot straight into the USB.

The USB that is running the program will also contain a bootable .EFI file.

I’ve tried looking how to do this with bcdedit, and cannot find anything, and I don’t really know any other search terms to try to find what I need, I’m at a loss here.

How can I programmatically reboot a windows machine into a flash drives .EFI file with powershell or (Electron) nodejs?


Get this bounty!!!

#StackBounty: #console #logging #powershell Advanced Logging Function

Bounty: 100

Way more blood, sweat, and tears have went into this then I would care to admit, but this has been a function I have been using in some shape or form for quite a while and it has taught me alot.

It does exactly what I want it to do ATM but happy to hear any suggestions on what could make it run more efficent. I am looking at making a buffer queue for the streamwriter to improve write performance but for for scripts is doesn’t really seem necessary, more just of a fun little addition to add.

Will most likely add the ability to write to event log next, but again there is no real need for it at this time.

function Write-Tee {
    Param(
        [Parameter(Mandatory=$False)]
        [Switch]$Close,
        [Parameter(Mandatory=$False)]
        [ValidateNotNullorEmpty()]
        [String]$Message,
        [Parameter(Mandatory=$False)]
        [ValidateSet('Fatal','Error','Warning','Info','Trace')]
        [String]$Severity,
        [Parameter(Mandatory=$False)]
        [Switch]$WriteToHost=$True,
        [Parameter(Mandatory=$False)]
        [Switch]$WriteToLog=$True,
        [Parameter(Mandatory=$False)]
        [Switch]$FirstRun=$False
    )
    Begin {
        $Logtime = [datetime]::Now
        #Function specific settings used for customization.
        [Int]$LoggingLevel  = 3
        [Bool]$WriteLog     = $True
        [Bool]$WriteConsole = $True
        [Int]$LogBuffer     = 25
        [String]$LogPath    = ''
        [String]$LogName    = ''

        Set-StrictMode -Version Latest
        $ErrorActionPreference = 'Stop'

        #Make sure previous streamwriters are closed out prior to starting script.
        If((test-path variable:WriteTee) -and $FirstRun) {
            Write-Tee -Close
        } ElseIf (!(test-path variable:WriteTee) -OR $FirstRun) {
            New-Variable -ErrorAction SilentlyContinue -Force -Name WriteTee -Value @{} -Scope Script
            $Script:WriteTee.RunOnce = $True
        }

        If ($WriteTee.RunOnce) {
            #Set important functional variables
            $Script:WriteTee.RunOnce = $False
            $Script:WriteTee.Computer = $env:COMPUTERNAME
            $Script:WriteTee.SID = [Security.Principal.WindowsIdentity]::GetCurrent().Name
            If ($Host.name -eq "Windows PowerShell ISE Host") {
                $Script:WriteTee.ForegroundColor = 'White'
                $Script:WriteTee.BackgroundColor = 'DarkMagenta'
            } Else {
                $Script:WriteTee.Host = (get-host).ui.rawui
                $Script:WriteTee.ForegroundColor = $Script:WriteTee.Host.ForegroundColor
                $Script:WriteTee.BackgroundColor = $Script:WriteTee.Host.BackgroundColor
            }

            #Dynamicly pull any script defined variables.
            If (Test-Path Variable:Script) {
                If ($Script.ContainsKey("WriteTee")) {
                    ForEach ($Key in $Script.WriteTee.GetEnumerator()) {
                        $Script:WriteTee.$($Key.Name) = $Key.Value
                    }
                }
            }

            #Dynamicly Convert REQUIRED funciton config to variables if not already defined.
            ForEach ($Var in ("LogLevel","WriteLog","WriteConsole","LogBuffer","LogPath","LogName")) {
                If (!$WriteTee.ContainsKey("$Var")) {
                    $WriteTee.Temp = Get-Variable -Name $Var -ValueOnly -ErrorAction SilentlyContinue
                    IF ($WriteTee.Temp -OR $Var -IN ("LogPath","LogName")) {
                        $WriteTee.$Var = $WriteTee.Temp
                    } Else {
                        Throw "$Var is not defined in either `$Script nor in the function config."
                    }
                }
                $WriteTee.Remove('Temp')
            }

            #Ensures there is a valid log level set.
            If ($WriteTee.LogLevel -LT 1 -OR $WriteTee.LogLevel -GT 5) {
                Write-Error "`$LogLevel does not contain a value between 1 and 5"
            }


            If ($WriteTee.WriteLog) {


                    $WriteTee.LogPaths = $WriteTee.LogPath,
                         $(split-path -parent $Script:MyInvocation.MyCommand.Definition),
                         $Env:UserProfile
                    #Verify that the logname is in a usable format.
                    Try {
                        $WriteTee.LogName = [System.IO.FileInfo]$WriteTee.LogName
                    } Catch {
                        $WriteTee.LogName = "$(([System.IO.FileInfo](split-path -leaf $Script:MyInvocation.MyCommand.Definition)).BaseName).log"
                    }

                    #Find the first usable log file.
                    Foreach ($Path in $WriteTee.LogPaths) {
                        If ($WriteTee.ContainsKey('LogFile')) {
                            Continue
                        } Else {
                            Try {
                                $Path = [System.IO.DirectoryInfo]$Path
                            } Catch {
                                #If you can't convert it, script can't use it.
                                Continue
                            }
                        }

                        #Ensure the directory exists and if not, create it.
                        If (![System.IO.Directory]::Exists($Path)) {
                            Try {
                                #Create the directory because .Net will error out if you try to create a file in a directory that doesn't exist yet.
                                New-Item -Path $Path.Parent.FullName -Name $Path.BaseName -ItemType 'Directory' -ErrorAction Stop -Force |Out-Null
                            } Catch {
                                Continue
                            }
                        }#End-If

                        #Check to see if there are any existing logs
                        $WriteTee.ExistingLogs = @(Get-ChildItem -LiteralPath $Path.FullName -Filter "$(([System.IO.FileInfo]$WriteTee.LogName).BaseName)*$(([System.IO.FileInfo]$WriteTee.LogName).Extension)" |Sort-Object)
                        If ($WriteTee.ExistingLogs.Count -GT 0) {
                            ForEach ($ExistingLog in $WriteTee.ExistingLogs) {
                                Try {
                                    [io.file]::OpenWrite($ExistingLog.FullName).close() |Out-Null
                                    $Script:WriteTee.LogFile = $ExistingLog.FullName
                                    break
                                } Catch {
                                    $WriteTee.LastLogName = $ExistingLog
                                    Continue
                                }
                            }
                            If ($Script:WriteTee.ContainsKey('LogFile')) {Break}
                        }#End-If

                        #If no previous logs can be added to create a new one.
                        switch ($WriteTee.ExistingLogs.Count) {
                            {$PSItem -EQ 0} {
                                $WriteTee.TestLogFile = Join-Path -Path $Path -ChildPath $WriteTee.LogName
                            }
                            {$PSItem -EQ 1} {
                                $WriteTee.TestLogFile = Join-Path -Path $Path -ChildPath ($WriteTee.LastLogName.basename + '[0]' + $WriteTee.LastLogName.Extension)
                            }

                            {$PSItem -GE 2} {
                                $WriteTee.TestLogFile = $WriteTee.LastLogName.FullName.Split('[]')
                                $WriteTee.TestLogFile = ($WriteTee.TestLogFile[0] + '[' + (([int]$WriteTee.TestLogFile[1]) + 1) + ']' + $WriteTee.TestLogFile[2])
                            }
                            Default {
                                Write-Host "If you are looking for an explanation of how you got here, I can tell you I don't have one. But what I do have are a very particular lack of answers that I have aquired over a very long career that make these problems a nightmare for people like me."
                                Continue
                                }
                        }#End-Switch

                        #Last but not least, try to create the file and hope it is successful.
                        Try {
                            [IO.File]::Create($WriteTee.TestLogFile, 1, 'None').close() |Out-Null
                            $Script:WriteTee.LogFile = $WriteTee.TestLogFile
                            $WriteTee.NewFile = $True
                            Break
                        } Catch {
                            Continue
                        }
                    }#End-ForEach

                #Rev up the StreamWriter
                $Script:WriteTee.StreamWriter = New-Object -TypeName System.IO.StreamWriter -ArgumentList "$($Script:WriteTee.LogFile)",$True,$([System.Text.Encoding]::Unicode)
                If ($WriteTee.ContainsKey('NewFile')) {
                    $Script:WriteTee.StreamWriter.WriteLine("Computer Name`tSecurity Principal`tDate`tTime`tScript Phase`tLine Number`tMessage")
                }
            }#EndIf
        }#EndIf

        #Convert easily readable severity to INT to determine log output level.


        Switch ($Severity) {
            'Trace'   {$WriteTee.ErrorLevel = '5'; $WriteTee.FGColor=$Script:WriteTee.ForegroundColor; $WriteTee.BGColor = $Script:WriteTee.BackgroundColor;}
            'Info'    {$WriteTee.ErrorLevel = '4'; $WriteTee.FGColor=$Script:WriteTee.ForegroundColor; $WriteTee.BGColor = $Script:WriteTee.BackgroundColor;}
            'Warning' {$WriteTee.ErrorLevel = '3'; $WriteTee.FGColor='Yellow'; $WriteTee.BGColor = 'Black';}
            'Error'   {$WriteTee.ErrorLevel = '2'; $WriteTee.FGColor='Red'; $WriteTee.BGColor = 'Black';}
            'Fatal'   {$WriteTee.ErrorLevel = '1'; $WriteTee.FGColor='Red'; $WriteTee.BGColor = 'Black';}
            Default   {$WriteTee.ErrorLevel = '0'}
        }#EndSwitch

        #If the script doesn't meet the minimum log level, disable output running.
        If ($WriteTee.ErrorLevel -GT $WriteTee.LogLevel) { 
            $WriteTee.Skip = $True
        } ElseIF($WriteTee.ErrorLevel -EQ 0 -AND !$Message) {
            $WriteTee.Skip = $True
            #Write-Error -message "Severity level must be defined"
        } Else {
            #Convert Date Time to more usable format.
            $WriteTee.Skip = $False
            $WriteTee.Time = $Logtime.ToString('HH:mm:ss,fff')
            $WriteTee.Date = $Logtime.ToString('MM-dd-yyyy')
            $WriteTee.Line = $MyInvocation.ScriptLineNumber
        }

    }#End-Begin

    Process {
        If ($WriteTee.Skip -EQ $False) {
            IF ($WriteTee.WriteConsole) {
                $WriteTee.OutConsole = "$($WriteTee.Date) $($WriteTee.Time) - $($Script.Phase) - $($WriteTee.Line) - $Message"
                Write-Host -Object $WriteTee.OutConsole -ForegroundColor $WriteTee.FGColor -BackgroundColor $WriteTee.BGColor
            }
            ## Write output to log file.
            IF ($WriteTee.WriteLog) {
                $WriteTee.OutLog = "$($Script:WriteTee.Computer)`t$($Script:WriteTee.SID)`t$($WriteTee.Date)`t$($WriteTee.Time)`t$($Script.Phase)`t$($WriteTee.Line)`t$Message"
                $Script:WriteTee.StreamWriter.WriteLine($WriteTee.OutLog)
            }
        }
    }#End-Process
    End {
        If ($Close -AND $Script:WriteTee) {
            $Script:WriteTee.StreamWriter.Flush()
            $Script:WriteTee.StreamWriter.Close()
            Remove-Variable -ErrorAction SilentlyContinue -Force -Name WriteTee -Scope Script
        }#End-If
    }#End-End

}
clear
$Script = @{}
$Script.WriteTee = @{}
$Script.WriteTee.LogLevel = 5
$Script.Phase = "Debug"

Write-Tee -Message "This is AWESOME!" -Severity Info
Write-Tee -Close


Get this bounty!!!

#StackBounty: #powershell #microsoft-office-365 #exchange-2013 #export #exchange-hybrid how to backup/export office 365 email to pst in…

Bounty: 50

We have a exchange hybrid environment. (some users are in onpremises exchange and some users are office 365. )

When we want to export emails from onpremis we use , below command to export mail box and archive.

 New-MailboxExportRequest -Mailbox "user" -FilePath \mysrvl$PSTMailbox-user.pst; New-MailboxExportRequest -Mailbox "user" -IsArchive  -FilePath \mysrvl$PSTMailbox-user-archive.pst -confirm:$false

New-MailboxExportRequest works fine for onpremis users not for office 365.
is there a way to export office 365 user mail box to pst using powershell ?

What i have tried so far:

I logged to office 365

$UserCredential = Get-Credential
Import-Module MSOnline

Connect-MsolService -Credential $UserCredential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication  Basic -AllowRedirection

Import-PSSession $Session

and tried New-MailboxExportRequest

But it generates an error. apparently office 365 dont know that command

PS C:Userspp> New-MailboxExportRequest
New-MailboxExportRequest : The term 'New-MailboxExportRequest' is not recognized as the name of a cmdlet, function,
script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is
correct and try again.
At line:1 char:1
+ New-MailboxExportRequest
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (New-MailboxExportRequest:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Also Get-Command *Export* results are as follows

enter image description here

Tried googling, yet could not find a viable option. can some one guide me please ? What is the compatible command in office environment to do this ?

PS:
I have tried https://www.codetwo.com/admins-blog/how-to-export-office-365-mailboxes-to-pst-using-ediscovery/ with E5 license and it works in the GUI perfectly. but my concern is even with e-discovery, and having license any possibility to do it with powershell ? i mean to script/automate via powershell ?


Get this bounty!!!

#StackBounty: #powershell #feature-activation Enable-SPFeature : Field not found

Bounty: 50

I have a feature that creates a library in a site collection root, as we have 30000 site collections I cant activate it manually, I have to activate it with powershell.

The problem is that when I activate it manually in the browser it works fine, but in powershell I get this error.

I checked the Feature Activated code and I didnt see code related to SPCurrent so I dont see why its failing.

Error is:

Enable-SPFeature : Field not found: 'Lists.ClientBillingInstructionsUrl'.
At D:lvxxx.SP.InstallersGit2.DMSR4.8.2ScriptsCustomFeatureUpgradeActivateFeatures.ps1:23 char:4
+    Enable-SPFeature -Identity $featureNameBillingInstructions -Url $spSiteCollec ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (Microsoft.Share...etEnableFeature:SPCmdletEnableFeature) [Enable-SPFeature], MissingFieldException
    + FullyQualifiedErrorId : Microsoft.SharePoint.PowerShell.SPCmdletEnableFeature

Feature activated code:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            String listUrl = Constants.Lists.ClientBillingInstructionsUrl;
            String listName = Constants.Lists.ClientBillingInstructionsName;

            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    using (SPSite site = new SPSite(((SPWeb)properties.Feature.Parent).Site.ID))
                    {
                        using (SPWeb web = site.OpenWeb(((SPWeb)properties.Feature.Parent).ID))
                        {
                            try
                            {
                                LoggingService.LogInfo(LoggingCategory.Feature, String.Format("Entered feature with name '{0}' and id '{1}' for list creation. List to create: (name: '{2}' , url: '{3}').",
                                                                                              properties.Feature.Definition.DisplayName,
                                                                                              properties.Feature.Definition.Id,
                                                                                              listName,
                                                                                              listUrl));

                                SPList billingInstructionsLibrary = web.CreateList(
                                                                        listUrl, //name
                                                                        "", //description
                                                                        101,  //type
                                                                        true, //showinQuickLaunch
                                                                        true, //allowManagementOfContentTypes
                                                                        true, //enableVersioning
                                                                        true, //enableMinorVersions
                                                                        DraftVisibilityType.Reader, //draftVisibilityType
                                                                        false, //forceCheckout 
                                                                        false //enableModeration
                                                                        );

                                if (billingInstructionsLibrary != null)
                                {
                                    #region library specific settings
                                    billingInstructionsLibrary.Title = "-"; //this is a trick to force quicklaunch displaytext to change. (it ignores casing updates on exact same words)
                                    billingInstructionsLibrary.Update();
                                    billingInstructionsLibrary.Title = listName;
                                    billingInstructionsLibrary.MajorVersionLimit = 5;
                                    billingInstructionsLibrary.MajorWithMinorVersionsLimit = 5;
                                    billingInstructionsLibrary.Update();
                                    #endregion

                                    #region add content types
                                    billingInstructionsLibrary.AddListContentType(new SPContentTypeId(Constants.ContentTypes.Client.PONumber.ID));
                                    billingInstructionsLibrary.AddListContentType(new SPContentTypeId(Constants.ContentTypes.Client.BillingMethod.ID));
                                    #endregion

                                    //save changes (because otherwise delete of default CT wont succeed
                                    billingInstructionsLibrary.Update();

                                    #region remove default content type
                                    //delete content type 'document'
                                    billingInstructionsLibrary.DeleteListContentType("Document");
                                    #endregion

                                    #region views

                                    //Modify View "All items"
                                    SPView allDocumentsView = null;
                                    foreach (SPView view in billingInstructionsLibrary.Views)
                                    {
                                        if (view.Title.ToLower() == "all documents")
                                        {
                                            allDocumentsView = view;
                                            break;
                                        }
                                    }

                                    if (allDocumentsView != null)
                                    {
                                        allDocumentsView.ViewFields.DeleteAll();
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.DocIcon_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.LinkFilename_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.Title_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.Created_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.CreatedBy_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.Modified_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.ModifiedBy_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.Version_Name);
                                        allDocumentsView.ViewFields.Add(Constants.DefaultFields.FileSize_name);

                                        //Set view settings
                                        allDocumentsView.RowLimit = 30;
                                        allDocumentsView.IncludeRootFolder = false;
                                        allDocumentsView.Paged = true;
                                        allDocumentsView.Query = String.Format("<OrderBy><FieldRef Name="{0}" Ascending="{1}" /></OrderBy>",
                                                                               Constants.DefaultFields.LinkFilename_Name,
                                                                               "TRUE");

                                        allDocumentsView.Update();
                                    }
                                    #endregion

                                    billingInstructionsLibrary.Update();
                                    LoggingService.LogInfo(LoggingCategory.Feature, String.Format("List with name '{0}' and url '{1}' created.", listName, listUrl));
                                }
                                else
                                {
                                    throw new Exception(String.Format("List with name '{0}' and url '{1}' could not be found.", listName, listUrl));
                                }
                            }
                            catch (Exception exception)
                            {
                                LoggingService.LogError(LoggingCategory.Feature, exception);
                            }
                        }
                    }
                });
            }
            catch (Exception exception)
            {
                LoggingService.LogError(LoggingCategory.Feature, exception);
            }
        }

and this is the powershell code I use to activate the feature

#Library creation
$featureNameBillingInstructionsEnabled = Get-SPFeature  -Site $spSiteCollection -Identity $featureNameBillingInstructions -ErrorAction SilentlyContinue;
if($featureNameBillingInstructionsEnabled-eq $null)
{
   Enable-SPFeature -Identity $featureNameBillingInstructions -Url $spSiteCollection.Url
}
else
{
   Write-Host "Feature $featureNameBillingInstructionsEnabled already enabled";
}


Get this bounty!!!

#StackBounty: #windows #powershell #windows-server-2016 #winrm #window-server-2012 Where is WinRMRemoteWMIUsers__ local group in Window…

Bounty: 200

With Windows Server 2012 R2 I can use the group WinRMRemoteWMIUsers__ to enable remote PowerShell execution via -CimSession for non-admin users. However, the group is missing on my Windows Server 2016 machines and I do not see any replacement for it except the Remote Management Users group. However it seems to me that it grants wider permissions than WinRMRemoteWMIUsers__.

Where is the WinRMRemoteWMIUsers__ group in Windows Server 2016?


Get this bounty!!!

#StackBounty: #powershell #csom #project-server Get Selection from Lookup Table CSOM PowerShell in Project Server

Bounty: 50

I have a custom field at the project level that is a lookup table (single select). I cannot for the life of me figure out how to get the value of the selection from the lookup table. I can get the lookup table:

$lookupTables = $projContext.LookupTables
$projContext.Load($lookupTables)
$projContext.ExecuteQuery()

$myLookupTable = $lookupTables.GetByGuid('GUID FOR LOOKUP TABLE')
$projContext.Load($myLookupTable)
$projContext.ExecuteQuery()

and I can get the field:
$custFields = $project.CustomFields
$projContext.Load($custFields)
$projContext.ExecuteQuery()

$myField = $custFields.GetByGuid([Guid]"{GUID FOR FIELD}") 
$projContext.Load($myField )
$projContext.ExecuteQuery()

When I look at values in myField everything looks ok. I can see the .LookupDefaultValue but when I try to get the selection of the Field, I’m not quite sure what to do. I’ve Tried:

$myfieldvalue = new-object Microsoft.SharePoint.Client.FieldUserValue($myField).LookupValue

But it comes out as Microsoft.SharePoint.Client.FieldUserValue

I’ve tried

$myfieldvalue = $myField .Value
$projContext.Load($myfieldvalue )
$projContext.ExecuteQuery()

but that blows up on the Load.


Get this bounty!!!

#StackBounty: #powershell #azure #azure-cloud-services #antimalware Setting Anti-Malware Enabled as default on Azure Cloud Service

Bounty: 50

OK, so this is a revised post as I can see some down-votes and the solution, for me, is still not working. As a background, deploying from Visual Studio to a Cloud Service in Azure will reset anti-malware back to original state (disabled). So I am trying to enable this by default.

Steps taken so far:

  1. Create Startup folder in the main web project
  2. Add to this folder startup.cmd file with the following:
    Powershell -ExecutionPolicy Unrestricted .Startupstartup.ps1 >> "c:logsstartup_ps_log.txt"
  1. Add to the same folder the powershell script startup.ps1:
    
    Set-AzureServiceAntimalwareExtension -ServiceName "myservicename" -AntimalwareConfiguration -Slot "Production"
  1. Modify the ServiceDefinition.csdef file in the Cloud Service project to call the startup task:
    <Startup priority="-2">
        <Task commandLine="startupstartup.cmd" executionContext="elevated" taskType="background" />      
    </Startup>

I deploy my solution and get the same result. Anti-malware is still disabled. If I fire up an RDP session into the VM and interrogate the log I can see it is running but failing to find the specific powershell command/script for AzureServiceAntimalwareExtension:

    Set-AzureServiceAntimalwareExtension : The term 
    'Set-AzureServiceAntimalwareExtension' is not recognized as the name of a 
    cmdlet, function, script file, or operable program. Check the spelling of the 
    name, or if a path was included, verify that the path is correct and try again.

Any suggestions?


Get this bounty!!!

#StackBounty: #powershell #powershell-v4.0 #powershell-remoting Constrained endpoint on specific user

Bounty: 50

I’m trying to create a PowerShell endpoint constraint that restricts an user to only execute the functions in a custom module I made.

The first thing I did is import-module mymodule.psm1 which allows me to run my modules fine withing my host system.

Then the following PS command creates the configuration file for the endpoint which allows the functions inside the brackets to be the only functions the user gets to execute.

New-PSSessionConfigurationFile -VisibleFunctions('Get-Command','Get-Info', 'CreateAD-User','Generate-Html','Change-Logon') -LanguageMode ‘ConstrainedLanguage’ –SessionType ‘RestrictedRemoteServer’ –Path ‘c:testhelpdesk.pssc’

Then I register the endpoint with

Register-PSSessionConfiguration –Name ‘HelpDesk’ -ShowSecurityDescriptorUI –Path ‘c:testhelpdesk.pssc’

and selected which user I want allow to have these constrains once the SecurityDescriptorUI pops up. Once I log into the user that I set up the constrains for with

Enter-PSSession -computername SRV1-AD -Credential $credential -ConfigurationName HelpDesk

These are the allowed cmdlets / functions that the user is allowed to execute. These are the default required cmdlets to allow remote connections into a system.

Image

How can I allow my custom module to be the only functions the endpoint allows users to execute? or How can I import my module into configuration file so it executes every time the HelpDesk end point configuration is used. I know that in the configuration file there’s a line to import modules but Import-Module is not actually a module an example of a module would be ActiveDirectory, if I’m able to find what module import-module is a part of I think I should be able to do a quick and dirty work around for this.

UPDATE

A dirty solution I found for this was to enter into the user’s session and disable all cmdlets / functions except the ones I want to allowed for example import-module & Get-Command with import-module I can manually import my custom module and my functions will be the only ones visible to user. But this is not a perfect solution because this means that I would need to download my module into every system I want this to take effect and it’s no longer a one to many solution. The ideal solution is to have my module locally stored, enter into a session with the registered end point and have my module already imported into the users account.

Enter-PSSession -computername SRV1-AD -Credential $credential -ConfigurationName HelpDesk

Further Update

User @prasoon-karunan-v suggested I used -ScriptsToProcess & FunctionDefinitions to import the module so I used the following command

New-PSSessionConfigurationFile -VisibleFunctions('Get-Command','Get-Info', 'CreateAD-User','Generate-Html','Change-Logon') -LanguageMode ‘ConstrainedLanguage’ –SessionType ‘RestrictedRemoteServer’ –Path ‘.EndPoint.pssc’ -ScriptsToProcess C:UsersAdministratorDesktopModulesImportM.psm1

In the configuration file I also set the functions I want to use like so

# Functions defined in this session configuration
FunctionDefinitions = 'Get-Command','Get-Info', 'CreateAD-User','Generate-Html','Change-Logon'

When I tried to establish a session it would throw the following error

Error1

Then I thought maybe it’s not working because were not telling the command to import anything were just pointing to the module file, so maybe I need to create a small script that imports the module then add it the configuration file. So that’s exactly what I did I created a small script with just,
import-module C:ModulesImportM.psm1 and then I went over to the .pssc
file and added this script to the ScriptsToProcess but I get the following error after I try to establish a session to the constrained endpoint.

Error

Language Mode is set to

LanguageMode = 'RestrictedLanguage'


Get this bounty!!!

#StackBounty: #c# #windows #powershell #usb-drive #computer-forensics How can I get timestamps on previously connected USB devices?

Bounty: 50

I’m trying to get an old PowerShell script to show the times of previously connected USB devices. After having read a few forensics blogs like this, I found this script from this blog. (Script by Jason Walker.)

Unfortunately it doesn’t show any timestamps or any other useful details about the devices. So I was hoping there should be a way to get that too. Only I fail to see how to incorporate this.

Function Get-USBHistory { 
 [CmdletBinding()] 
Param 
( 
[parameter(ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] 
    [alias("CN","Computer")] 
    [String[]]$ComputerName=$Env:COMPUTERNAME, 
    [Switch]$Ping     
) 

 Begin { 
     $TempErrorAction = $ErrorActionPreference 
     $ErrorActionPreference = "Stop" 
     $Hive   = "LocalMachine" 
     $Key    = "SYSTEMCurrentControlSetEnumUSBSTOR" 
  } 

  Process 
  {             
     $USBDevices      = @() 
     $ComputerCounter = 0         

     ForEach($Computer in $ComputerName) 
     { 
        $USBSTORSubKeys1 = @() 
        $ChildSubkeys    = @() 
        $ChildSubkeys1   = @() 

        $ComputerCounter++         
        $Computer = $Computer.Trim().ToUpper() 
        Write-Progress -Activity "Collecting USB history" -Status "Retrieving USB history from $Computer" -PercentComplete (($ComputerCounter/($ComputerName.Count)*100)) 


        If($Ping) 
        { 
           If(-not (Test-Connection -ComputerName $Computer -Count 1 -Quiet)) 
           { 
              Write-Warning "Ping failed on $Computer" 
              Continue 
           } 
        }#end if ping  

         Try 
         { 
            $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($Hive,$Computer) 
            $USBSTORKey = $Reg.OpenSubKey($Key) 
            $USBSTORSubKeys1  = $USBSTORKey.GetSubKeyNames() 
         }#end try              
         Catch 
         { 
            Write-Warning "There was an error connecting to the registry on $Computer or USBSTOR key not found. Ensure the remote registry service is running on the remote machine." 
         }#end catch 

         ForEach($SubKey1 in $USBSTORSubKeys1) 
         {     
            $ErrorActionPreference = "Continue" 
            $Key2 = "SYSTEMCurrentControlSetEnumUSBSTOR$SubKey1" 
            $RegSubKey2  = $Reg.OpenSubKey($Key2) 
            $SubkeyName2 = $RegSubKey2.GetSubKeyNames() 

            $ChildSubkeys   += "$Key2$SubKeyName2" 
            $RegSubKey2.Close()         
         }#end foreach SubKey1 

         ForEach($Child in $ChildSubkeys) 
         { 

            If($Child -match " ") 
            { 
               $BabySubkey = $null 
               $ChildSubkey1 = ($Child.split(" "))[0] 

               $SplitChildSubkey1 = $ChildSubkey1.split("") 

               0..4 | Foreach{ [String]$BabySubkey += ($SplitChildSubkey1[$_]) + ""}  

               $ChildSubkeys1 += $BabySubkey + ($Child.split(" ")[-1]) 
               $ChildSubkeys1 += $ChildSubkey1 

            } 
            Else 
            { 
               $ChildSubkeys1 += $Child 
            } 
                $ChildSubKeys1.count 
         }#end foreach ChildSubkeys 

         ForEach($ChildSubkey1 in $ChildSubkeys1) 
         {     
            $USBKey      = $Reg.OpenSubKey($ChildSubkey1) 
            $USBDevice   = $USBKey.GetValue('FriendlyName')  
            If($USBDevice) 
            {     
               $USBDevices += New-Object -TypeName PSObject -Property @{ 
                     USBDevice = $USBDevice 
                     Computer  = $Computer 
                     Serial    = $ChildSubkey1.Split("")[-1] 
                       } 
             } 
                 $USBKey.Close()                                           
          }#end foreach ChildSubKey2 

                 $USBSTORKey.Close()            
         #Display results         
     $USBDevices | Select Computer,USBDevice,Serial 
     }#end foreach computer  

  }#end process 

  End 
  {         
     #Set error action preference back to original setting         
     $ErrorActionPreference = $TempErrorAction          
  } 

}#end function 

And the C# code:

using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
class Program
{
    static void Main(string[] args)
    {
        string usbStor = @"SYSTEMControlSet001EnumUSBSTOR";
        using (var keyUsbStor = Registry.LocalMachine.OpenSubKey(usbStor))
        {
            var usbDevices = from className in keyUsbStor.GetSubKeyNames()
                             let keyUsbClass = keyUsbStor.OpenSubKey(className)
                             from instanceName in keyUsbClass.GetSubKeyNames()
                             let keyUsbInstance = new RegistryKeyEx(keyUsbClass.OpenSubKey(instanceName))
                             select new
                             {
                                 UsbName = keyUsbInstance.Key.GetValue("FriendlyName"),
                                 ConnectTime = keyUsbInstance.LastWriteTime
                             };
            foreach (var usbDevice in usbDevices.OrderBy(x => x.ConnectTime))
            {
                Console.WriteLine("({0}) -- '{1}'", usbDevice.ConnectTime, usbDevice.UsbName);
            }
        }
    }
}
/// <summary>
/// Wraps a RegistryKey object and corresponding last write time.
/// </summary>
/// <remarks>
/// .NET doesn't expose the last write time for a registry key 
/// in the RegistryKey class, so P/Invoke is required.
/// </remarks>
public class RegistryKeyEx
{
    #region P/Invoke Declarations
    // This declaration is intended to be used for the last write time only. int is used
    // instead of more convenient types so that dummy values of 0 reduce verbosity.
    [DllImport("advapi32.dll", EntryPoint = "RegQueryInfoKey", CallingConvention = CallingConvention.Winapi, SetLastError = true)]
    extern private static int RegQueryInfoKey(
        SafeRegistryHandle hkey,
        int lpClass,
        int lpcbClass,
        int lpReserved,
        int lpcSubKeys,
        int lpcbMaxSubKeyLen,
        int lpcbMaxClassLen,
        int lpcValues,
        int lpcbMaxValueNameLen,
        int lpcbMaxValueLen,
        int lpcbSecurityDescriptor,
        IntPtr lpftLastWriteTime);
    #endregion
    #region Public Poperties
    /// <summary>
    /// Gets the registry key owned by the info object.
    /// </summary>
    public RegistryKey Key { get; private set; }
    /// <summary>
    /// Gets the last write time for the corresponding registry key.
    /// </summary>
    public DateTime LastWriteTime { get; private set; }
    #endregion
    /// <summary>
    /// Creates and initializes a new RegistryKeyInfo object from the provided RegistryKey object.
    /// </summary>
    /// <param name="key">RegistryKey component providing a handle to the key.</param>
    public RegistryKeyEx(RegistryKey key)
    {
        Key = key;
        SetLastWriteTime();
    }
    /// <summary>
    /// Creates and initializes a new RegistryKeyInfo object from a registry key path string.
    /// </summary>
    /// <param name="parent">Parent key for the key being loaded.</param>
    /// <param name="keyName">Path to the registry key.</param>
    public RegistryKeyEx(RegistryKey parent, string keyName)
        : this(parent.OpenSubKey(keyName))
    { }
    /// <summary>
    /// Queries the currently set registry key through P/Invoke for the last write time.
    /// </summary>
    private void SetLastWriteTime()
    {
        Debug.Assert(Key != null, "RegistryKey component must be initialized");
        GCHandle pin = new GCHandle();
        long lastWriteTime = 0;
        try
        {
            pin = GCHandle.Alloc(lastWriteTime, GCHandleType.Pinned);
            if (RegQueryInfoKey(Key.Handle, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pin.AddrOfPinnedObject()) == 0)
            {
                LastWriteTime = DateTime.FromFileTime((long)pin.Target);
            }
            else
            {
                LastWriteTime = DateTime.MinValue;
            }
        }
        finally
        {
            if (pin.IsAllocated)
            {
                pin.Free();
            }
        }
    }
}

(Sorry, I can’t get the PSH code to highlight correctly.)

How can I use this to improve the script?


Update: 2017-11-06

Following @iRon’s suggestion, I tried to directly access the registry path: HKLMSYSTEMCurrentControlSetEnumUSBSTOR<drive>Propertie‌​s, using RegEdit, but then I got a permission error, which is strange, as my user account is Admin. (This is on Win8.1)

enter image description here


Get this bounty!!!