NN.MrfkCommands.psm1
#Region './Private/Get-CompInf.ps1' 0 function Get-CompInf { [CmdletBinding()] param ( [Parameter(Mandatory)][array]$allMecmComputers, [Parameter(Mandatory)][array]$allCpuInfo, [Parameter(Mandatory)][array]$allAdComputers, [Parameter(Mandatory)][array]$allModelInfo, [Parameter(Mandatory)][string]$hostname ) process { $notes = New-Object -TypeName System.Collections.ArrayList $mecmComputer = $allMecmComputers.where({$_.Name -eq $hostname}) $cpuInfo = $allCpuInfo.where({$_.SystemName -eq $hostname}) $adComputer = $allAdComputers.where({$_.Name -eq $hostname}) $modelInfo = $allModelInfo.where({$_.ResourceID -eq $mecmComputer.ResourceId}) if ($mecmComputer.agentname) { $heartbeatIndex = $mecmComputer.agentname.IndexOf("Heartbeat Discovery") $lastHeartbeat = $mecmComputer.agenttime[$heartbeatIndex] } [PSCustomObject]@{ Hostname = $mecmComputer.Name Username = $mecmComputer.LastLogonUserName MACAddress = $mecmComputer.MACAddresses Model = $modelInfo.Name SN = $modelInfo.IdentifyingNumber GUID = $mecmComputer.SMBIOSGUID CreatedAt = $mecmComputer.CreationDate DeviceOSBuild = $mecmComputer.BuildExt OS = $mecmComputer.OperatingSystemNameandVersion "Enabled(AD)" = $adComputer.Enabled LastHeartbeat = $lastHeartbeat CpuName = $cpuInfo.Name Notes = $notes } } } #EndRegion './Private/Get-CompInf.ps1' 40 #Region './Private/Register-Autofill.ps1' 0 $Splat = @{ "CommandName" = "New-ShippingLabel" "ParameterName" = "location" "ScriptBlock" = { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) $AllLocationNames = (Get-SnipeLocations).name | Sort-Object $AllLocationNames.Where({ $_ -like "$wordToComplete*" }).ForEach({ "`"$_`"" }) } } Register-ArgumentCompleter @Splat #EndRegion './Private/Register-Autofill.ps1' 16 #Region './Public/Disable-OutlookElements.ps1' 0 function Disable-OutlookElements { param ( [Parameter(Mandatory=$true)][string]$hostname ) $tnc = tnc $hostname if ($tnc.PingSucceeded) { if ((Invoke-command -computername $hostname {Get-ItemProperty 'HKLM:\Software\Microsoft\Office\Outlook\Addins\Gecko.Ephorte.Outlook.Main' -Name LoadBehavior}) -eq 0) { "Outlook Elements is already deactivated on $hostname" } else { $response = Invoke-command -computername $hostname { New-Item 'HKLM:\Software\Microsoft\Office\Outlook\Addins\Gecko.Ephorte.Outlook.Main' -Force | Out-Null (New-ItemProperty 'HKLM:\Software\Microsoft\Office\Outlook\Addins\Gecko.Ephorte.Outlook.Main' -Name 'LoadBehavior' -Value 0 -PropertyType dword).LoadBehavior } if ($response -eq 0) { "Success" } else { $response "Failed" } } } else { "Computer is offline" } } #EndRegion './Public/Disable-OutlookElements.ps1' 27 #Region './Public/Get-AdmCreds.ps1' 0 function Get-AdmCreds { param ( [string]$admCredsPath = "$env:USERPROFILE\.creds\Windows\adm_creds.xml" ) if (!(Test-Path $admCredsPath)) { #Create directories for adm_creds $admCredsDir = $admCredsPath.Substring(0, $admCredsPath.lastIndexOf('\')) if (!(Test-Path $admCredsDir)) { New-Item -ItemType Directory $admCredsDir | Out-Null } #Create adm_creds file Get-Credential -Message "Enter admin credentials" | Export-Clixml $admCredsPath } else { Import-Clixml $admCredsPath } } #EndRegion './Public/Get-AdmCreds.ps1' 19 #Region './Public/Get-Computer.ps1' 0 function Get-Computer { [CmdletBinding(DefaultParameterSetName="List computers")] param ( [Parameter(Mandatory,ValueFromPipeline,Position=0,ParameterSetName="Get computer by hostname")][string]$hostname, [pscredential]$credential, [Parameter(ParameterSetName="List computers")][switch]$ListComputers, [string]$OutCsvPath ) begin { $allCpuInfoQry = @" select distinct SMS_G_System_PROCESSOR.* from SMS_R_System inner join SMS_G_System_PROCESSOR on SMS_G_System_PROCESSOR.ResourceID = SMS_R_System.ResourceId "@ Write-Information "$(Get-Date -Format "hh:mm:ss") Creating CimSession" $cimsession = New-CimSession -Credential $credential -ComputerName sccm-ps.intern.mrfylke.no -ErrorAction Stop Write-Information "$(Get-Date -Format "hh:mm:ss") Fetching all AD computers" $allAdComputers = Get-ADComputer -Filter * Write-Information "$(Get-Date -Format "hh:mm:ss") Fetching MECM computers" $allMecmComputers = Get-CimInstance -Query "Select * from SMS_R_System" -Namespace root/SMS/site_PS1 -CimSession $cimsession Write-Information "$(Get-Date -Format "hh:mm:ss") Fetching all CPU info" $allCpuInfo = Get-CimInstance -Query $allCpuInfoQry -Namespace root/SMS/site_PS1 -CimSession $cimsession Write-Information "$(Get-Date -Format "hh:mm:ss") Fetching all model info" $allModelInfo = Get-CimInstance -Query "Select * from SMS_G_System_Computer_System_Product" -Namespace root/SMS/site_PS1 -CimSession $cimsession $compInfExport = New-Object -TypeName System.Collections.ArrayList } process { switch ($PsCmdlet.ParameterSetName) { "List computers" { $CompInfDef = ${function:Get-CompInf}.ToString() $compInfExport = $allMecmComputers | ForEach-Object -ThrottleLimit 5000 -Parallel { ${function:Get-CompInf} = $using:CompInfDef Write-Information "$(Get-Date -Format "hh:mm:ss") Fetching CompInf for `"$($_.Name)`"" $CompInfSplat = @{ "allMecmComputers" = $using:allMecmComputers "allCpuInfo" = $using:allCpuInfo "allAdComputers" = $using:allAdComputers "allModelInfo" = $using:allModelInfo "hostname" = $_.Name } Get-CompInf @CompInfSplat Write-Information "$(Get-Date -Format "hh:mm:ss") Completed fetching info for computer `"$($_.Name)`"" } } "Get computer by hostname" { $CompInfSplat = @{ "allMecmComputers" = $allMecmComputers "allCpuInfo" = $allCpuInfo "allAdComputers" = $allAdComputers "allModelInfo" = $allModelInfo "hostname" = $hostname } $currentCompInf = Get-CompInf @CompInfSplat $null = $compInfExport.Add($currentCompInf) } } } end { if ($OutCsvPath) { $compInfExport | Export-Csv $OutCsvPath } else { $compInfExport } } } #EndRegion './Public/Get-Computer.ps1' 74 #Region './Public/Get-FreeHostnames.ps1' 0 function Get-FreeHostnames { param ( [Parameter(Mandatory,HelpMessage="Example inputs: `"LT-SADM-`" or `"PC-SADM-`"")][ValidateScript({ $_ -like "*-*-" }, ErrorMessage="Please provide a valid input. Valid inputs are `"<device-type>-<locationname>-`" Example: `"LT-SADM-`" or `"PC-VROM-`"" )][string]$filter, [pscredential]$credential, [int]$count ) $cimsession = New-CimSession -Credential $credential -ComputerName sccm-ps.intern.mrfylke.no -ErrorAction Stop $allMecmComputers = Get-CimInstance -Query "Select * from SMS_R_System" -Namespace root/SMS/site_PS1 -CimSession $cimsession $pcNumArr = $allMecmComputers.where({$_.Name -like "*$filter*"}).Name.Replace("$filter","","OrdinalIgnoreCase") -replace "^0+","" | Sort-Object $freePcNumArr = (1..999).where({$_ -notin $pcNumArr}) if ($count) { $freePcNumArr = $freePcNumArr | Select-Object -First $count } $freePcNumArr.ForEach({ $num = ([string]$_).PadLeft(3,'0') "$filter$num" }) } #todo: add $HostnamePrefix="PC","TB","LT" and $LocationName="SADM","VROM",etc. #todo: Get all locaiton shorts from hostnames currently in MECM and validatescript #EndRegion './Public/Get-FreeHostnames.ps1' 27 #Region './Public/Invoke-Camfix.ps1' 0 function Invoke-Camfix { param ( [Parameter(Mandatory=$true)][string]$hostname ) $tnc = tnc $hostname if ($tnc.PingSucceeded) { if (Invoke-command -computername $hostname -ScriptBlock {Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows Media Foundation\Platform\' -Name EnableFrameServerMode}) { "Camfix is already installed on $hostname" } else { $response = Invoke-command -computername $hostname -ScriptBlock {(New-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows Media Foundation\Platform\' -Name 'EnableFrameServerMode' -Value 0 -PropertyType dword).EnableFrameServerMode} if ($response -eq 0) { "Success" } else { $response "Failed" } } } else { "Computer is offline" } } #EndRegion './Public/Invoke-Camfix.ps1' 22 #Region './Public/Invoke-PCCheck.ps1' 0 function Invoke-PCCheck { param ( [Parameter(Mandatory)][string]$displayName ) $notes = New-Object -TypeName System.Collections.ArrayList # Check if there is a active EXO sessions $psSessions = Get-PSSession | Select-Object -Property State, Name If (!(($psSessions -like '@{State=Opened; Name=ExchangeOnlineInternalSession*').Count -gt 0)) { throw "Run Connect-ExchangeOnline before running this function." } #Get userinfo $adUser = Get-ADUser -Credential $(Get-AdmCreds) -Filter {DisplayName -eq $displayName} -Properties * if (!$adUser) { throw "Can't find user `"$displayName`" in AD." } $adUsername = $aduser.Name $homeDir = $adUser.HomeDirectory #Create home dir if ($homeDir) { [bool]$homeDirExists = Invoke-gsudo { if (!(Test-Path $using:homeDir)) { New-Item -ItemType Directory $using:homeDir | Out-Null } # Get the ACL for an existing folder $ExistingACL = Get-Acl -Path $using:homeDir # Sets Full Control permission for the given user on This Folder, Subfolders and Files $Permissions = "intern\$using:adUsername", 'FullControl', 'ContainerInherit,ObjectInherit', 'None', 'Allow' # Create a new FileSystemAccessRule object $Rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $Permissions # Modify the existing ACL to include the new rule $ExistingACL.SetAccessRule($Rule) # Apply the modified access rule to the folder $ExistingACL | Set-Acl -Path $using:homeDir | Out-Null Test-Path $using:homeDir } } else { [bool]$homeDirExists = $false $notes.Add("There's no homedir path on the AD user.") } #Check if mailbox is in Exchange Online if (Get-InstalledModule ExchangeOnlineManagement) { Import-Module ExchangeOnlineManagement } else { Install-Module ExchangeOnlineManagement -Force } [bool]$migrated = Get-EXOMailbox $adUser.mail -ErrorAction SilentlyContinue #Reset AD password Set-ADAccountPassword $adUser.Name -Credential $(Get-AdmCreds) -NewPassword (Read-Host "Please enter a new password for user `"$($adUser.Name)`"" -AsSecureString) -Reset -Server "dc01.intern.mrfylke.no" [PSCustomObject]@{ DisplayName = $adUser.DisplayName Username = $adUser.Name UPN = $adUser.UserPrincipalName ADLocation = $adUser.DistinguishedName HomeDirExists = $homeDirExists Migrated = $migrated Notes = $notes } } #EndRegion './Public/Invoke-PCCheck.ps1' 69 #Region './Public/New-LocalAdmin.ps1' 0 function New-LocalAdmin { param ( [Parameter(Mandatory)][string]$username, [Parameter(Mandatory)][string]$hostname ) $admUsername = "adm_$username" $UPN = "$admUsername@intern.mrfylke.no" #Create user in AD if (!(Get-ADUser -Credential $(Get-AdmCreds) -filter {UserPrincipalName -eq $UPN})) { $result = Get-ADuser -Credential $(Get-AdmCreds) $username $firstName = $result.GivenName $lastName = $result.Surname New-ADUser -Credential $(Get-AdmCreds) -name "$firstName $lastName (Admin)" -SamAccountName $admUsername -Path "OU=Lokaladmins,OU=Adminbrukere,DC=intern,DC=mrfylke,DC=no" -UserPrincipalName $UPN -Description "Lokaladmin på maskin $hostname" -GivenName "$firstName" -Surname "$lastName" -DisplayName "$firstName $lastName (Admin)" -AccountPassword ("Molde123!" | ConvertTo-SecureString -AsPlainText) -ChangePasswordAtLogon $true -Enabled $true } else { Write-Information -MessageData "UPN `"$UPN`" already exists" -InformationAction Continue } $discordHookPath = "$env:USERPROFILE\.creds\Discord\workHookUri.xml" if (!(Test-Path $discordHookPath)) { $discordHookDir = $discordHookPath.Substring(0, $discordHookPath.lastIndexOf('\')) if (!(Test-Path $discordHookDir)) { New-Item -ItemType Directory $discordHookDir | Out-Null } Read-Host -AsSecureString "Enter Discord webhook uri" | Export-Clixml $discordHookPath } $taskName = "Localadmin for $admUsername on $hostname" $task = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue #Add ADUser to admin role on the given hostname if (Test-Connection $hostname -Count 1 -Quiet) { Invoke-Command -Credential $(Get-AdmCreds) -ComputerName $hostname -ScriptBlock { if (Get-LocalGroupMember -Group Administratorer -Member "intern\$using:admUsername" -ErrorAction SilentlyContinue) { "User `"$using:admUsername`" is already an administrator on `"$using:hostname`"" } else { Add-LocalGroupMember -Group Administratorer -Member "intern\$using:admUsername" } } if ($task) { Send-DiscordMessage -uri (Import-Clixml $discordHookPath | ConvertFrom-SecureString -AsPlainText) -message "Task `"$taskName`" has been completed." $task | Unregister-ScheduledTask -Confirm:$false } } elseif (!$task) { $module1 = "C:\Users\danhol13\repos\mrfk-commands\Output\mrfk-commands.psm1" $module2 = "C:\Users\danhol13\repos\NN.Notifications\Output\NN.Notifications.psm1" $action = New-ScheduledTaskAction -Execute "pwsh.exe" -Argument "-WindowStyle Hidden -command `"Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass -Force;Import-Module `"$module1`";Import-Module `"$module2`";New-LocalAdmin -username $username -hostname $hostname`"" #Run every 5 minutes $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 5) $null = Register-ScheduledTask -Action $action -Trigger $trigger -TaskName $taskName -Description "Add `"$admUsername`" as localadmin on `"$hostname`"" Send-DiscordMessage -uri (Import-Clixml $discordHookPath | ConvertFrom-SecureString -AsPlainText) -message "Task `"$taskName`" has been created." } } #todo: move scheduled tasks with discord implementation to their own functions #EndRegion './Public/New-LocalAdmin.ps1' 58 #Region './Public/New-ShippingLabel.ps1' 0 function New-ShippingLabel { [CmdletBinding()] param ( [Parameter(Mandatory)][ValidateScript({ $_ -in (Get-SnipeLocations).name })][string]$location, [Parameter(Mandatory)][string]$displayname, [int]$copies = 1, [string]$mobile, [string]$PrinterNetworkPath = "\\sr-safecom-sla1\PR-STORLABEL-SSDSK" ) begin { $RequiredModulesNameArray = @("NN.SnipeIT","NN.WindowsSetup") $RequiredModulesNameArray.ForEach({ if (Get-InstalledModule $_ -ErrorAction SilentlyContinue) { Import-Module $_ -Force } else { Install-Module $_ -Force } }) #Install RSAT Install-RSAT -WUServerBypass } process { #Get the selected locations address $locationResult = Get-SnipeLocations -name $location $locationName = $locationResult.address $address = $locationResult.address2 $postalCode = $locationResult.zip $city = $locationResult.city if (!$mobile) { #Search AD for phonenumber [string]$mobile = (Get-ADUser -Filter {DisplayName -like $displayname} -Properties mobile).mobile } if ($location) { #Get current default printer $defaultPrinter = (Get-CimInstance -Class Win32_Printer).where({$_.Default -eq $true}).Name #Set printer named PR-STORLABEL-SSDSK to default printer if (!(Get-Printer -Name $PrinterNetworkPath -ErrorAction SilentlyContinue)) { (New-Object -ComObject WScript.Network).AddWindowsPrinterConnection($PrinterNetworkPath) } (New-Object -ComObject WScript.Network).SetDefaultPrinter($PrinterNetworkPath) #Create new Word document $WordObj = New-Object -ComObject Word.Application $null = $WordObj.Documents.Add() #Set page size and margins $WordObj.Selection.PageSetup.PageHeight = "192mm" $WordObj.Selection.PageSetup.PageWidth = "102mm" $WordObj.Selection.PageSetup.TopMargin = "12,7mm" $WordObj.Selection.PageSetup.BottomMargin = "12,7mm" $WordObj.Selection.PageSetup.LeftMargin = "12,7mm" $WordObj.Selection.PageSetup.RightMargin = "12,7mm" #Insert content $WordObj.Selection.Font.Bold = 1 $WordObj.Selection.TypeText("Mottaker: ") $WordObj.Selection.Font.Bold = 0 $WordObj.Selection.TypeText("$displayname $mobile") $WordObj.Selection.TypeParagraph() $WordObj.Selection.Font.Bold = 1 $WordObj.Selection.TypeText("Addresse: ") $WordObj.Selection.Font.Bold = 0 $WordObj.Selection.TypeText("$locationName $address $postalCode $city") (1..$copies).ForEach({ #Send To Default Printer $WordObj.PrintOut() }) #Change default printer back to the previous value (New-Object -ComObject WScript.Network).SetDefaultPrinter("$defaultPrinter") #Close File without saving $WordObj.ActiveDocument.Close(0) $WordObj.quit() } } } #EndRegion './Public/New-ShippingLabel.ps1' 93 |