Add headless macOS CLI workflow
This commit is contained in:
@@ -1,6 +1,21 @@
|
|||||||
#region Console functions
|
#region Console functions
|
||||||
|
|
||||||
|
function Test-IsWindowsPlatform
|
||||||
|
{
|
||||||
|
return ([Environment]::OSVersion.Platform -eq [System.PlatformID]::Win32NT)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-AppDoEvents
|
||||||
|
{
|
||||||
|
if("System.Windows.Forms.Application" -as [type])
|
||||||
|
{
|
||||||
|
[System.Windows.Forms.Application]::DoEvents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# https://stackoverflow.com/questions/40617800/opening-powershell-script-and-hide-command-prompt-but-not-the-gui
|
# https://stackoverflow.com/questions/40617800/opening-powershell-script-and-hide-command-prompt-but-not-the-gui
|
||||||
|
if(Test-IsWindowsPlatform)
|
||||||
|
{
|
||||||
Add-Type -Name Window -Namespace Console -MemberDefinition '
|
Add-Type -Name Window -Namespace Console -MemberDefinition '
|
||||||
[DllImport("Kernel32.dll")]
|
[DllImport("Kernel32.dll")]
|
||||||
public static extern IntPtr GetConsoleWindow();
|
public static extern IntPtr GetConsoleWindow();
|
||||||
@@ -17,9 +32,11 @@ public static extern bool SetConsoleIcon(IntPtr hIcon);
|
|||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern int SendMessage(int hWnd, uint wMsg, uint wParam, IntPtr lParam);
|
public static extern int SendMessage(int hWnd, uint wMsg, uint wParam, IntPtr lParam);
|
||||||
'
|
'
|
||||||
|
}
|
||||||
|
|
||||||
function Show-Console
|
function Show-Console
|
||||||
{
|
{
|
||||||
|
if(-not (Test-IsWindowsPlatform)) { return }
|
||||||
$consolePtr = [Console.Window]::GetConsoleWindow()
|
$consolePtr = [Console.Window]::GetConsoleWindow()
|
||||||
|
|
||||||
# Hide = 0,
|
# Hide = 0,
|
||||||
@@ -41,6 +58,7 @@ function Show-Console
|
|||||||
|
|
||||||
function Hide-Console
|
function Hide-Console
|
||||||
{
|
{
|
||||||
|
if(-not (Test-IsWindowsPlatform)) { return }
|
||||||
$consolePtr = [Console.Window]::GetConsoleWindow()
|
$consolePtr = [Console.Window]::GetConsoleWindow()
|
||||||
#0 hide
|
#0 hide
|
||||||
[Console.Window]::ShowWindow($consolePtr, 0) | Out-Null
|
[Console.Window]::ShowWindow($consolePtr, 0) | Out-Null
|
||||||
@@ -94,17 +112,19 @@ function Initialize-CloudAPIManagement
|
|||||||
)
|
)
|
||||||
|
|
||||||
$PSModuleAutoloadingPreference = "none"
|
$PSModuleAutoloadingPreference = "none"
|
||||||
|
$global:hideUI = ($Silent -eq $true)
|
||||||
|
$global:SilentBatchFile = $SilentBatchFile
|
||||||
|
|
||||||
$global:wpfNS = "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'"
|
$global:wpfNS = "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'"
|
||||||
|
|
||||||
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
|
if($global:hideUI -ne $true)
|
||||||
Add-Type -AssemblyName PresentationFramework
|
{
|
||||||
|
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
|
||||||
|
Add-Type -AssemblyName PresentationFramework
|
||||||
|
}
|
||||||
|
|
||||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
|
|
||||||
$global:hideUI = ($Silent -eq $true)
|
|
||||||
$global:SilentBatchFile = $SilentBatchFile
|
|
||||||
|
|
||||||
if($tenantId)
|
if($tenantId)
|
||||||
{
|
{
|
||||||
Write-Host "Using Tenant Id: $tenantId"
|
Write-Host "Using Tenant Id: $tenantId"
|
||||||
@@ -163,7 +183,7 @@ function Initialize-CloudAPIManagement
|
|||||||
$global:txtSplashTitle.Text = ("Initializing Cloud API PowerShell Management")
|
$global:txtSplashTitle.Text = ("Initializing Cloud API PowerShell Management")
|
||||||
|
|
||||||
$global:SplashScreen.Show() | Out-Null
|
$global:SplashScreen.Show() | Out-Null
|
||||||
[System.Windows.Forms.Application]::DoEvents()
|
Invoke-AppDoEvents
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -204,15 +224,15 @@ function Initialize-CloudAPIManagement
|
|||||||
{
|
{
|
||||||
$global:txtSplashText.Text = "Unblock files"
|
$global:txtSplashText.Text = "Unblock files"
|
||||||
}
|
}
|
||||||
[System.Windows.Forms.Application]::DoEvents()
|
Invoke-AppDoEvents
|
||||||
Unblock-AllFiles $PSScriptRoot
|
Unblock-AllFiles $PSScriptRoot
|
||||||
|
|
||||||
if($global:hideUI -ne $true)
|
if($global:hideUI -ne $true)
|
||||||
{
|
{
|
||||||
$global:txtSplashText.Text = "Load core module"
|
$global:txtSplashText.Text = "Load core module"
|
||||||
}
|
}
|
||||||
[System.Windows.Forms.Application]::DoEvents()
|
Invoke-AppDoEvents
|
||||||
Import-Module ($PSScriptRoot + "\Core.psm1") -Force -Global
|
Import-Module (Join-Path $PSScriptRoot "Core.psm1") -Force -Global
|
||||||
|
|
||||||
Start-CoreApp $View
|
Start-CoreApp $View
|
||||||
}
|
}
|
||||||
|
|||||||
132
Core.psm1
132
Core.psm1
@@ -14,6 +14,14 @@ function Get-ModuleVersion
|
|||||||
'3.9.6'
|
'3.9.6'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Invoke-AppDoEvents
|
||||||
|
{
|
||||||
|
if("System.Windows.Forms.Application" -as [type])
|
||||||
|
{
|
||||||
|
[System.Windows.Forms.Application]::DoEvents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Initialize-Window
|
function Initialize-Window
|
||||||
{
|
{
|
||||||
param($xamlFile)
|
param($xamlFile)
|
||||||
@@ -67,7 +75,27 @@ function Start-CoreApp
|
|||||||
$global:AppRootFolder = $PSScriptRoot
|
$global:AppRootFolder = $PSScriptRoot
|
||||||
|
|
||||||
# Load all modules in the Modules folder
|
# Load all modules in the Modules folder
|
||||||
$global:modulesPath = [IO.Path]::GetDirectoryName($PSCommandPath) + "\Extensions"
|
$global:modulesPath = Join-Path ([IO.Path]::GetDirectoryName($PSCommandPath)) "Extensions"
|
||||||
|
|
||||||
|
if($global:hideUI -eq $true)
|
||||||
|
{
|
||||||
|
$global:skipModules = @(
|
||||||
|
"Compare.psm1",
|
||||||
|
"Copy.psm1",
|
||||||
|
"Documentation.psm1",
|
||||||
|
"DocumentationCustom.psm1",
|
||||||
|
"DocumentationHTML.psm1",
|
||||||
|
"DocumentationMD.psm1",
|
||||||
|
"DocumentationWord.psm1",
|
||||||
|
"IntuneAssignments.psm1",
|
||||||
|
"IntuneFilterUsage.psm1",
|
||||||
|
"IntuneTools.psm1"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$global:skipModules = @()
|
||||||
|
}
|
||||||
|
|
||||||
Add-DefaultSettings
|
Add-DefaultSettings
|
||||||
|
|
||||||
@@ -122,7 +150,7 @@ function Start-CoreApp
|
|||||||
$global:MainAppStarted = $false
|
$global:MainAppStarted = $false
|
||||||
|
|
||||||
Set-SplashWindowText "Initialize views"
|
Set-SplashWindowText "Initialize views"
|
||||||
[System.Windows.Forms.Application]::DoEvents()
|
Invoke-AppDoEvents
|
||||||
|
|
||||||
Invoke-ModuleFunction "Invoke-InitializeModule"
|
Invoke-ModuleFunction "Invoke-InitializeModule"
|
||||||
|
|
||||||
@@ -176,8 +204,6 @@ function Start-CoreApp
|
|||||||
Write-Log "SilentBatchFile $($global:SilentBatchFile) not found" 3
|
Write-Log "SilentBatchFile $($global:SilentBatchFile) not found" 3
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Invoke-ModuleFunction "Invoke-ShowMainWindow"
|
|
||||||
|
|
||||||
Invoke-ModuleFunction "Invoke-InitSilentBatchJob"
|
Invoke-ModuleFunction "Invoke-InitSilentBatchJob"
|
||||||
|
|
||||||
Start-RunSilentBatchJob
|
Start-RunSilentBatchJob
|
||||||
@@ -199,13 +225,13 @@ function Start-RunSilentBatchJob
|
|||||||
|
|
||||||
function Import-AllModules
|
function Import-AllModules
|
||||||
{
|
{
|
||||||
foreach($file in (Get-Item -path "$($global:modulesPath)\*.psm1"))
|
foreach($file in (Get-Item -path (Join-Path $global:modulesPath "*.psm1")))
|
||||||
{
|
{
|
||||||
$fileName = [IO.Path]::GetFileName($file)
|
$fileName = [IO.Path]::GetFileName($file)
|
||||||
if($skipModules -contains $fileName) { Write-Warning "Module $fileName excluded"; continue; }
|
if($skipModules -contains $fileName) { Write-Warning "Module $fileName excluded"; continue; }
|
||||||
|
|
||||||
Set-SplashWindowText "Import module $fileName"
|
Set-SplashWindowText "Import module $fileName"
|
||||||
[System.Windows.Forms.Application]::DoEvents()
|
Invoke-AppDoEvents
|
||||||
|
|
||||||
$module = Import-Module $file -PassThru -Force -Global -ErrorAction SilentlyContinue
|
$module = Import-Module $file -PassThru -Force -Global -ErrorAction SilentlyContinue
|
||||||
if($module)
|
if($module)
|
||||||
@@ -422,7 +448,14 @@ function Set-XamlProperty
|
|||||||
{
|
{
|
||||||
if($obj)
|
if($obj)
|
||||||
{
|
{
|
||||||
$obj."$propertyName" = $value
|
if(-not ($obj.PSObject.Properties.Name -contains $propertyName))
|
||||||
|
{
|
||||||
|
$obj | Add-Member -MemberType NoteProperty -Name $propertyName -Value $value -Force
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$obj."$propertyName" = $value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -571,15 +604,15 @@ function Set-BatchProperties
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if($obj -is [System.Windows.Controls.CheckBox])
|
if($obj.PSObject.Properties.Name -contains "IsChecked")
|
||||||
{
|
{
|
||||||
$obj.IsChecked = $prop.Value -eq $true
|
$obj.IsChecked = $prop.Value -eq $true
|
||||||
}
|
}
|
||||||
elseif($obj -is [System.Windows.Controls.TextBox])
|
elseif($obj.PSObject.Properties.Name -contains "Text")
|
||||||
{
|
{
|
||||||
$obj.Text = $prop.Value
|
$obj.Text = $prop.Value
|
||||||
}
|
}
|
||||||
elseif($obj -is [System.Windows.Controls.ComboBox])
|
elseif($obj.PSObject.Properties.Name -contains "SelectedValue")
|
||||||
{
|
{
|
||||||
$obj.SelectedValue = $prop.Value
|
$obj.SelectedValue = $prop.Value
|
||||||
}
|
}
|
||||||
@@ -601,6 +634,60 @@ function Set-BatchProperties
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
function New-HeadlessControl
|
||||||
|
{
|
||||||
|
param(
|
||||||
|
[string]$Name,
|
||||||
|
[ValidateSet("TextBox","CheckBox","ComboBox","Label","DataGrid")]
|
||||||
|
[string]$Type = "TextBox"
|
||||||
|
)
|
||||||
|
|
||||||
|
$control = [PSCustomObject]@{
|
||||||
|
Name = $Name
|
||||||
|
Focusable = $true
|
||||||
|
Visibility = "Visible"
|
||||||
|
IsEnabled = $true
|
||||||
|
Text = ""
|
||||||
|
IsChecked = $false
|
||||||
|
SelectedValue = $null
|
||||||
|
ItemsSource = @()
|
||||||
|
Content = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Type -eq "DataGrid")
|
||||||
|
{
|
||||||
|
$control.Focusable = $false
|
||||||
|
}
|
||||||
|
|
||||||
|
$control
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-HeadlessForm
|
||||||
|
{
|
||||||
|
param($Controls)
|
||||||
|
|
||||||
|
$form = [PSCustomObject]@{
|
||||||
|
Controls = @{}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($control in $Controls)
|
||||||
|
{
|
||||||
|
$form.Controls[$control.Name] = $control
|
||||||
|
}
|
||||||
|
|
||||||
|
$form | Add-Member -MemberType ScriptMethod -Name FindName -Value {
|
||||||
|
param($name)
|
||||||
|
$this.Controls[$name]
|
||||||
|
}
|
||||||
|
|
||||||
|
$form | Add-Member -MemberType ScriptMethod -Name RegisterName -Value {
|
||||||
|
param($name, $control)
|
||||||
|
$this.Controls[$name] = $control
|
||||||
|
}
|
||||||
|
|
||||||
|
$form
|
||||||
|
}
|
||||||
|
|
||||||
#region Dialogs
|
#region Dialogs
|
||||||
|
|
||||||
function Show-AboutDialog
|
function Show-AboutDialog
|
||||||
@@ -1204,6 +1291,21 @@ function Expand-FileName
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
function Get-CloudApiDataFolder
|
||||||
|
{
|
||||||
|
if($env:LOCALAPPDATA)
|
||||||
|
{
|
||||||
|
return (Join-Path $env:LOCALAPPDATA "CloudAPIPowerShellManagement")
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Test-IsWindowsPlatform)
|
||||||
|
{
|
||||||
|
return (Join-Path $env:USERPROFILE "AppData/Local/CloudAPIPowerShellManagement")
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Join-Path $HOME "Library/Application Support/CloudAPIPowerShellManagement")
|
||||||
|
}
|
||||||
|
|
||||||
#region Save/Read Settings functions
|
#region Save/Read Settings functions
|
||||||
########################################################################
|
########################################################################
|
||||||
#
|
#
|
||||||
@@ -1231,7 +1333,7 @@ function Initialize-JsonSettings
|
|||||||
{
|
{
|
||||||
if(-not $global:JSonSettingFile)
|
if(-not $global:JSonSettingFile)
|
||||||
{
|
{
|
||||||
$global:JSonSettingFile = "$($env:LOCALAPPDATA)\CloudAPIPowerShellManagement\Settings.json"
|
$global:JSonSettingFile = Join-Path (Get-CloudApiDataFolder) "Settings.json"
|
||||||
$fi = [IO.FileInfo]$global:JSonSettingFile
|
$fi = [IO.FileInfo]$global:JSonSettingFile
|
||||||
if($fi.Exists -eq $false)
|
if($fi.Exists -eq $false)
|
||||||
{
|
{
|
||||||
@@ -1548,7 +1650,7 @@ function Add-RegKeyToSettings
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
$keyObj = Get-Item -Path $regKey -ErrorAction SilentlyContinue
|
$keyObj = Get-Item -Path $regKey -ErrorAction SilentlyContinue
|
||||||
foreach($keyValue in ($keyObj.GetValueNames() | Sort))
|
foreach($keyValue in ($keyObj.GetValueNames() | Sort-Object))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1560,7 +1662,7 @@ function Add-RegKeyToSettings
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($subKey in ($keyObj.GetSubKeyNames() | Sort))
|
foreach($subKey in ($keyObj.GetSubKeyNames() | Sort-Object))
|
||||||
{
|
{
|
||||||
|
|
||||||
$settingObjSub = [ordered]@{}
|
$settingObjSub = [ordered]@{}
|
||||||
@@ -1967,7 +2069,7 @@ function Add-DefaultSettings
|
|||||||
Value = ""
|
Value = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($color in ([System.Drawing.Color].GetProperties() | Where { $_.PropertyType -eq [System.Drawing.Color] } | Sort -Property Name | Select Name).Name)
|
foreach($color in ([System.Drawing.Color].GetProperties() | Where { $_.PropertyType -eq [System.Drawing.Color] } | Sort-Object -Property Name | Select Name).Name)
|
||||||
{
|
{
|
||||||
$script:lstColors += [PSCustomObject]@{
|
$script:lstColors += [PSCustomObject]@{
|
||||||
Name = $color
|
Name = $color
|
||||||
@@ -2286,7 +2388,7 @@ function Add-ViewItem
|
|||||||
if($viewObject.ViewInfo.Permissions -is [Object[]] -and $viewObject.ViewInfo.Permissions -notcontains $scope) { $viewObject.ViewInfo.Permissions += $scope }
|
if($viewObject.ViewInfo.Permissions -is [Object[]] -and $viewObject.ViewInfo.Permissions -notcontains $scope) { $viewObject.ViewInfo.Permissions += $scope }
|
||||||
}
|
}
|
||||||
|
|
||||||
if($viewItem.Icon -or [IO.File]::Exists(($global:AppRootFolder + "\Xaml\Icons\$($viewItem.Id).xaml")))
|
if($global:hideUI -ne $true -and ($viewItem.Icon -or [IO.File]::Exists(($global:AppRootFolder + "\Xaml\Icons\$($viewItem.Id).xaml"))))
|
||||||
{
|
{
|
||||||
$ctrl = Get-XamlObject ($global:AppRootFolder + "\Xaml\Icons\$((?? $viewItem.Icon $viewItem.Id)).xaml")
|
$ctrl = Get-XamlObject ($global:AppRootFolder + "\Xaml\Icons\$((?? $viewItem.Icon $viewItem.Id)).xaml")
|
||||||
$viewItem | Add-Member -NotePropertyName "IconImage" -NotePropertyValue $ctrl
|
$viewItem | Add-Member -NotePropertyName "IconImage" -NotePropertyValue $ctrl
|
||||||
|
|||||||
@@ -105,9 +105,12 @@ function Invoke-InitializeModule
|
|||||||
Write-Log "Microsoft Intune PowerShell is being decomissioned. Please change to a supported app eg Microsoft Graph or a custom app!" 2
|
Write-Log "Microsoft Intune PowerShell is being decomissioned. Please change to a supported app eg Microsoft Graph or a custom app!" 2
|
||||||
}
|
}
|
||||||
|
|
||||||
$viewPanel = Get-XamlObject ($global:AppRootFolder + "\Xaml\EndpointManagerPanel.xaml") -AddVariables
|
$viewPanel = $null
|
||||||
|
if($global:hideUI -ne $true)
|
||||||
Set-EMViewPanel $viewPanel
|
{
|
||||||
|
$viewPanel = Get-XamlObject (Join-Path $global:AppRootFolder "Xaml/EndpointManagerPanel.xaml") -AddVariables
|
||||||
|
Set-EMViewPanel $viewPanel
|
||||||
|
}
|
||||||
|
|
||||||
#Add menu group and items
|
#Add menu group and items
|
||||||
$global:EMViewObject = (New-Object PSObject -Property @{
|
$global:EMViewObject = (New-Object PSObject -Property @{
|
||||||
|
|||||||
@@ -138,8 +138,8 @@ function Invoke-InitializeModule
|
|||||||
}) "MSAL"
|
}) "MSAL"
|
||||||
|
|
||||||
$script:MSALUseWAM = Get-SettingValue "UseWAM"
|
$script:MSALUseWAM = Get-SettingValue "UseWAM"
|
||||||
if($script:MSALUseWAM -and $PSVersionTable.PSVersion.Major -lt 7) {
|
if($script:MSALUseWAM -and ($PSVersionTable.PSVersion.Major -lt 7 -or -not (Test-IsWindowsPlatform))) {
|
||||||
Write-Log "WAM is only supported in PowerShell 7 and later. Disabling WAM" 2
|
Write-Log "WAM is only supported on Windows with PowerShell 7 and later. Disabling WAM" 2
|
||||||
$script:MSALUseWAM = $false
|
$script:MSALUseWAM = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +268,7 @@ function Get-MSALUserInfo
|
|||||||
### Only get user info from home tenant
|
### Only get user info from home tenant
|
||||||
$global:Me = $tmpMe
|
$global:Me = $tmpMe
|
||||||
Write-Log "Get profile picture"
|
Write-Log "Get profile picture"
|
||||||
$global:profilePhoto = "$($env:LOCALAPPDATA)\CloudAPIPowerShellManagement\$($global:Me.Id).jpeg"
|
$global:profilePhoto = Join-Path (Get-CloudApiDataFolder) "$($global:Me.Id).jpeg"
|
||||||
MSGraph\Invoke-GraphRequest "me/photos/48x48/`$value" -OutFile $global:profilePhoto -SkipAuthentication -NoError | Out-Null
|
MSGraph\Invoke-GraphRequest "me/photos/48x48/`$value" -OutFile $global:profilePhoto -SkipAuthentication -NoError | Out-Null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -517,17 +517,17 @@ function Add-MSALPrereq
|
|||||||
|
|
||||||
$DLLFiles = @()
|
$DLLFiles = @()
|
||||||
if($PSVersionTable.PSVersion.Major -ge 7) {
|
if($PSVersionTable.PSVersion.Major -ge 7) {
|
||||||
$DLLFiles += [IO.FileInfo]($ScriptRoot + "\Bin\Microsoft.IdentityModel.Abstractions.dll")
|
$DLLFiles += [IO.FileInfo](Join-Path $ScriptRoot "Bin/Microsoft.IdentityModel.Abstractions.dll")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$DLLFiles += [IO.FileInfo]($ScriptRoot + "\Bin\6.35.0\Microsoft.IdentityModel.Abstractions.dll")
|
$DLLFiles += [IO.FileInfo](Join-Path $ScriptRoot "Bin/6.35.0/Microsoft.IdentityModel.Abstractions.dll")
|
||||||
}
|
}
|
||||||
$DLLFiles += [IO.FileInfo]($ScriptRoot + "\Bin\Microsoft.Identity.Client.dll")
|
$DLLFiles += [IO.FileInfo](Join-Path $ScriptRoot "Bin/Microsoft.Identity.Client.dll")
|
||||||
if($script:MSALUseWAM) {
|
if($script:MSALUseWAM) {
|
||||||
$DLLFiles += [IO.FileInfo]($ScriptRoot + "\BIN\$MSALDLLPath\Microsoft.Identity.Client.Extensions.Msal.dll")
|
$DLLFiles += [IO.FileInfo](Join-Path $ScriptRoot "Bin/$MSALDLLPath/Microsoft.Identity.Client.Extensions.Msal.dll")
|
||||||
$DLLFiles += [IO.FileInfo]($ScriptRoot + "\BIN\$MSALDLLPath\Microsoft.Identity.Client.Broker.dll")
|
$DLLFiles += [IO.FileInfo](Join-Path $ScriptRoot "Bin/$MSALDLLPath/Microsoft.Identity.Client.Broker.dll")
|
||||||
$DLLFiles += [IO.FileInfo]($ScriptRoot + "\BIN\$MSALDLLPath\Microsoft.Identity.Client.Desktop.dll")
|
$DLLFiles += [IO.FileInfo](Join-Path $ScriptRoot "Bin/$MSALDLLPath/Microsoft.Identity.Client.Desktop.dll")
|
||||||
$DLLFiles += [IO.FileInfo]($ScriptRoot + "\BIN\$MSALDLLPath\Microsoft.Identity.Client.NativeInterop.dll")
|
$DLLFiles += [IO.FileInfo](Join-Path $ScriptRoot "Bin/$MSALDLLPath/Microsoft.Identity.Client.NativeInterop.dll")
|
||||||
}
|
}
|
||||||
|
|
||||||
$DLLFiles | ForEach-Object {
|
$DLLFiles | ForEach-Object {
|
||||||
@@ -570,7 +570,7 @@ function Add-MSALPrereq
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Add-Type -Path ($ScriptRoot + "\CS\TokenCacheHelperEx.cs") -ReferencedAssemblies $RequiredAssemblies -IgnoreWarnings
|
Add-Type -Path (Join-Path $ScriptRoot "CS/TokenCacheHelperEx.cs") -ReferencedAssemblies $RequiredAssemblies -IgnoreWarnings
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -809,7 +809,7 @@ function Get-MsalAuthenticationToken
|
|||||||
{
|
{
|
||||||
# Login hung on rare occations
|
# Login hung on rare occations
|
||||||
# Workaround: Added DoEvents
|
# Workaround: Added DoEvents
|
||||||
[System.Windows.Forms.Application]::DoEvents()
|
Invoke-AppDoEvents
|
||||||
Start-Sleep -Seconds 1
|
Start-Sleep -Seconds 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -954,7 +954,7 @@ function Get-MSALApp
|
|||||||
|
|
||||||
if($global:SkipTokenCacheHelperEx -ne $true -and (Get-SettingValue "CacheMSALToken"))
|
if($global:SkipTokenCacheHelperEx -ne $true -and (Get-SettingValue "CacheMSALToken"))
|
||||||
{
|
{
|
||||||
[TokenCacheHelperEx]::EnableSerialization($msalApp.UserTokenCache, "%LOCALAPPDATA%\CloudAPIPowerShellManagement\msalcahce.bin3")
|
[TokenCacheHelperEx]::EnableSerialization($msalApp.UserTokenCache, (Join-Path (Get-CloudApiDataFolder) "msalcahce.bin3"))
|
||||||
}
|
}
|
||||||
$script:MSALAllApps += $msalApp
|
$script:MSALAllApps += $msalApp
|
||||||
}
|
}
|
||||||
@@ -1350,7 +1350,7 @@ function Connect-MSALUser
|
|||||||
|
|
||||||
if((Get-SettingValue "CacheMSALToken"))
|
if((Get-SettingValue "CacheMSALToken"))
|
||||||
{
|
{
|
||||||
[TokenCacheHelperEx]::EnableSerialization($app.UserTokenCache, "%LOCALAPPDATA%\CloudAPIPowerShellManagement\msalcahce.bin3")
|
[TokenCacheHelperEx]::EnableSerialization($app.UserTokenCache, (Join-Path (Get-CloudApiDataFolder) "msalcahce.bin3"))
|
||||||
}
|
}
|
||||||
|
|
||||||
### Silent login
|
### Silent login
|
||||||
|
|||||||
@@ -782,7 +782,7 @@ function Add-GraphObjectProperties
|
|||||||
|
|
||||||
if($objects.Count -gt 0 -and $SortProperty -and ($objects[0] | GM -MemberType NoteProperty -Name $SortProperty))
|
if($objects.Count -gt 0 -and $SortProperty -and ($objects[0] | GM -MemberType NoteProperty -Name $SortProperty))
|
||||||
{
|
{
|
||||||
$objects = $objects | sort -Property $SortProperty
|
$objects = $objects | Sort-Object -Property $SortProperty
|
||||||
}
|
}
|
||||||
|
|
||||||
$objects
|
$objects
|
||||||
@@ -1400,12 +1400,77 @@ function Invoke-SilentBatchJob
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function New-GraphSilentBatchForm
|
||||||
|
{
|
||||||
|
param($Controls)
|
||||||
|
|
||||||
|
$form = New-HeadlessForm $Controls
|
||||||
|
|
||||||
|
foreach($control in $Controls)
|
||||||
|
{
|
||||||
|
New-Variable -Name $control.Name -Value $control -Force -Scope Global
|
||||||
|
}
|
||||||
|
|
||||||
|
$form
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-GraphSilentExportForm
|
||||||
|
{
|
||||||
|
$controls = @(
|
||||||
|
(New-HeadlessControl -Name "txtExportPath" -Type "TextBox"),
|
||||||
|
(New-HeadlessControl -Name "txtExportNameFilter" -Type "TextBox"),
|
||||||
|
(New-HeadlessControl -Name "chkAddObjectType" -Type "CheckBox"),
|
||||||
|
(New-HeadlessControl -Name "chkExportAssignments" -Type "CheckBox"),
|
||||||
|
(New-HeadlessControl -Name "chkAddCompanyName" -Type "CheckBox"),
|
||||||
|
(New-HeadlessControl -Name "dgObjectsToExport" -Type "DataGrid")
|
||||||
|
)
|
||||||
|
|
||||||
|
$form = New-GraphSilentBatchForm $controls
|
||||||
|
Set-XamlProperty $form "txtExportPath" "Text" (?? (Get-Setting "" "LastUsedRoot") (Get-SettingValue "RootFolder"))
|
||||||
|
Set-XamlProperty $form "chkAddObjectType" "IsChecked" $true
|
||||||
|
Set-XamlProperty $form "chkExportAssignments" "IsChecked" (Get-SettingValue "ExportAssignments")
|
||||||
|
Set-XamlProperty $form "chkAddCompanyName" "IsChecked" (Get-SettingValue "AddCompanyName")
|
||||||
|
|
||||||
|
$form
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-GraphSilentImportForm
|
||||||
|
{
|
||||||
|
$path = Get-Setting "" "LastUsedFullPath"
|
||||||
|
if($path)
|
||||||
|
{
|
||||||
|
$path = [IO.Directory]::GetParent($path).FullName
|
||||||
|
}
|
||||||
|
|
||||||
|
$controls = @(
|
||||||
|
(New-HeadlessControl -Name "txtImportPath" -Type "TextBox"),
|
||||||
|
(New-HeadlessControl -Name "txtImportNameFilter" -Type "TextBox"),
|
||||||
|
(New-HeadlessControl -Name "lblMigrationTableInfo" -Type "Label"),
|
||||||
|
(New-HeadlessControl -Name "chkAddObjectType" -Type "CheckBox"),
|
||||||
|
(New-HeadlessControl -Name "chkImportScopes" -Type "CheckBox"),
|
||||||
|
(New-HeadlessControl -Name "chkImportAssignments" -Type "CheckBox"),
|
||||||
|
(New-HeadlessControl -Name "chkReplaceDependencyIDs" -Type "CheckBox"),
|
||||||
|
(New-HeadlessControl -Name "cbImportType" -Type "ComboBox"),
|
||||||
|
(New-HeadlessControl -Name "dgObjectsToImport" -Type "DataGrid")
|
||||||
|
)
|
||||||
|
|
||||||
|
$form = New-GraphSilentBatchForm $controls
|
||||||
|
Set-XamlProperty $form "txtImportPath" "Text" (?? $path (Get-SettingValue "RootFolder"))
|
||||||
|
Set-XamlProperty $form "chkAddObjectType" "IsChecked" $true
|
||||||
|
Set-XamlProperty $form "chkImportAssignments" "IsChecked" (Get-SettingValue "ImportAssignments")
|
||||||
|
Set-XamlProperty $form "chkImportScopes" "IsChecked" (Get-SettingValue "ImportScopeTags")
|
||||||
|
Set-XamlProperty $form "chkReplaceDependencyIDs" "IsChecked" $true
|
||||||
|
Set-XamlProperty $form "cbImportType" "ItemsSource" $script:lstImportTypes
|
||||||
|
Set-XamlProperty $form "cbImportType" "SelectedValue" (Get-SettingValue "ImportType" "alwaysImport")
|
||||||
|
|
||||||
|
$form
|
||||||
|
}
|
||||||
|
|
||||||
function Start-GraphSilentBulkExport
|
function Start-GraphSilentBulkExport
|
||||||
{
|
{
|
||||||
param($settingsObj)
|
param($settingsObj)
|
||||||
|
|
||||||
$script:exportForm = Get-XamlObject ($global:AppRootFolder + "\Xaml\BulkExportForm.xaml") -AddVariables
|
$script:exportForm = New-GraphSilentExportForm
|
||||||
if(-not $script:exportForm) { return }
|
|
||||||
|
|
||||||
$script:exportObjects = Get-GraphBatchObjectTypes $settingsObj.BulkExport
|
$script:exportObjects = Get-GraphBatchObjectTypes $settingsObj.BulkExport
|
||||||
|
|
||||||
@@ -1414,8 +1479,6 @@ function Start-GraphSilentBulkExport
|
|||||||
if(-not $viewObj.Title) { continue }
|
if(-not $viewObj.Title) { continue }
|
||||||
|
|
||||||
if($viewObj.ObjectType.ShowButtons -is [Object[]] -and $viewObj.ObjectType.ShowButtons -notcontains "Export") { continue }
|
if($viewObj.ObjectType.ShowButtons -is [Object[]] -and $viewObj.ObjectType.ShowButtons -notcontains "Export") { continue }
|
||||||
|
|
||||||
Add-GraphExportExtensions $script:exportForm 0 $viewObj.ObjectType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Set-BatchProperties $settingsObj.BulkExport $script:exportForm
|
Set-BatchProperties $settingsObj.BulkExport $script:exportForm
|
||||||
@@ -1449,8 +1512,7 @@ function Start-GraphSilentBulkImport
|
|||||||
{
|
{
|
||||||
param($settingsObj)
|
param($settingsObj)
|
||||||
|
|
||||||
$script:importForm = Get-XamlObject ($global:AppRootFolder + "\Xaml\BulkImportForm.xaml") -AddVariables
|
$script:importForm = New-GraphSilentImportForm
|
||||||
if(-not $script:importForm) { return }
|
|
||||||
|
|
||||||
# Get all objects but not selected
|
# Get all objects but not selected
|
||||||
# This will allow dependencies
|
# This will allow dependencies
|
||||||
@@ -1479,11 +1541,10 @@ function Start-GraphSilentBulkImport
|
|||||||
if(-not $viewObj.Title) { continue }
|
if(-not $viewObj.Title) { continue }
|
||||||
|
|
||||||
if($viewObj.ObjectType.ShowButtons -is [Object[]] -and $viewObj.ObjectType.ShowButtons -notcontains "Import") { continue }
|
if($viewObj.ObjectType.ShowButtons -is [Object[]] -and $viewObj.ObjectType.ShowButtons -notcontains "Import") { continue }
|
||||||
|
|
||||||
Add-GraphImportExtensions $script:importForm 0 $viewObj.ObjectType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Set-BatchProperties $settingsObj.BulkImport $script:importForm
|
Set-BatchProperties $settingsObj.BulkImport $script:importForm
|
||||||
|
Set-XamlProperty $script:importForm "lblMigrationTableInfo" "Content" (Get-MigrationTableInfo)
|
||||||
|
|
||||||
$global:dgObjectsToImport.ItemsSource = @($script:importObjects)
|
$global:dgObjectsToImport.ItemsSource = @($script:importObjects)
|
||||||
|
|
||||||
@@ -2358,7 +2419,7 @@ function Get-GraphFileObjects
|
|||||||
}
|
}
|
||||||
|
|
||||||
$fileArr = @()
|
$fileArr = @()
|
||||||
foreach($file in (Get-Item -path "$path\*.json" @params))
|
foreach($file in (Get-Item -path (Join-Path $path "*.json") @params))
|
||||||
{
|
{
|
||||||
if($ObjectType.LoadObject)
|
if($ObjectType.LoadObject)
|
||||||
{
|
{
|
||||||
@@ -2864,7 +2925,7 @@ function Add-GroupMigrationObject
|
|||||||
# Export group info to json file for possible import
|
# Export group info to json file for possible import
|
||||||
$grouspPath = Join-Path $path "Groups"
|
$grouspPath = Join-Path $path "Groups"
|
||||||
if(-not (Test-Path $grouspPath)) { mkdir -Path $grouspPath -Force -ErrorAction SilentlyContinue | Out-Null }
|
if(-not (Test-Path $grouspPath)) { mkdir -Path $grouspPath -Force -ErrorAction SilentlyContinue | Out-Null }
|
||||||
$fileName = "$grouspPath\$((Remove-InvalidFileNameChars $groupObj.displayName)).json"
|
$fileName = Join-Path $grouspPath "$((Remove-InvalidFileNameChars $groupObj.displayName)).json"
|
||||||
Save-GraphObjectToFile $groupObj $fileName
|
Save-GraphObjectToFile $groupObj $fileName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2907,7 +2968,7 @@ function Add-GraphMigrationObject
|
|||||||
# Export group info to json file for possible import
|
# Export group info to json file for possible import
|
||||||
$grouspPath = Join-Path $path "Groups"
|
$grouspPath = Join-Path $path "Groups"
|
||||||
if(-not (Test-Path $grouspPath)) { mkdir -Path $grouspPath -Force -ErrorAction SilentlyContinue | Out-Null }
|
if(-not (Test-Path $grouspPath)) { mkdir -Path $grouspPath -Force -ErrorAction SilentlyContinue | Out-Null }
|
||||||
$fileName = "$grouspPath\$((Remove-InvalidFileNameChars $graphObj.displayName)).json"
|
$fileName = Join-Path $grouspPath "$((Remove-InvalidFileNameChars $graphObj.displayName)).json"
|
||||||
Save-GraphObjectToFile $graphObj $fileName
|
Save-GraphObjectToFile $graphObj $fileName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3050,7 +3111,7 @@ function Get-GraphMigrationObjectsFromFile
|
|||||||
if($global:GraphMigrationTable)
|
if($global:GraphMigrationTable)
|
||||||
{
|
{
|
||||||
$fi = [IO.FileInfo]$global:GraphMigrationTable
|
$fi = [IO.FileInfo]$global:GraphMigrationTable
|
||||||
$groupFi = [IO.FileInfo]($fi.DirectoryName + "\Groups\$((Remove-InvalidFileNameChars $migTableGroupName)).json")
|
$groupFi = [IO.FileInfo](Join-Path (Join-Path $fi.DirectoryName "Groups") "$((Remove-InvalidFileNameChars $migTableGroupName)).json")
|
||||||
}
|
}
|
||||||
|
|
||||||
if($groupFi.Exists -eq $true)
|
if($groupFi.Exists -eq $true)
|
||||||
@@ -3197,13 +3258,13 @@ function Add-GraphDependencyObjects
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if([IO.Directory]::Exists(($importPath + "\" + $dep)))
|
if([IO.Directory]::Exists((Join-Path $importPath $dep)))
|
||||||
{
|
{
|
||||||
$path = ($importPath + "\" + $dep)
|
$path = (Join-Path $importPath $dep)
|
||||||
}
|
}
|
||||||
elseif([IO.Directory]::Exists(($parentPath + "\" + $dep)))
|
elseif([IO.Directory]::Exists((Join-Path $parentPath $dep)))
|
||||||
{
|
{
|
||||||
$path = ($parentPath + "\" + $dep)
|
$path = (Join-Path $parentPath $dep)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -3674,7 +3735,7 @@ function Invoke-GraphBatchRequest
|
|||||||
$retryAfter = 0
|
$retryAfter = 0
|
||||||
$tmpResults = Invoke-GraphRequest -Url "`$batch" -Body $json -Method "POST"
|
$tmpResults = Invoke-GraphRequest -Url "`$batch" -Body $json -Method "POST"
|
||||||
|
|
||||||
foreach($batchResult in ($tmpResults.responses | Sort -Property Id))
|
foreach($batchResult in ($tmpResults.responses | Sort-Object -Property Id))
|
||||||
{
|
{
|
||||||
if($batchResult.Status -ge 300 -or -not $batchResult.body)
|
if($batchResult.Status -ge 300 -or -not $batchResult.body)
|
||||||
{
|
{
|
||||||
@@ -4151,7 +4212,7 @@ function Show-GraphObjectInfo
|
|||||||
if($prop.Name.Contains('@') -or $prop.Name.Contains('#')) { continue }
|
if($prop.Name.Contains('@') -or $prop.Name.Contains('#')) { continue }
|
||||||
$objProps += ([PSCustomObject]@{ Name=$prop.Name;Value=$prop })
|
$objProps += ([PSCustomObject]@{ Name=$prop.Name;Value=$prop })
|
||||||
}
|
}
|
||||||
$objProps = $objProps | sort -Property Name
|
$objProps = $objProps | Sort-Object -Property Name
|
||||||
Set-XamlProperty $script:detailsForm "lstObjectProperties" "ItemsSource" $objProps
|
Set-XamlProperty $script:detailsForm "lstObjectProperties" "ItemsSource" $objProps
|
||||||
|
|
||||||
Add-XamlEvent $script:detailsForm "btnObjectColumnsReset" "Add_Click" -scriptBlock ([scriptblock]{
|
Add-XamlEvent $script:detailsForm "btnObjectColumnsReset" "Add_Click" -scriptBlock ([scriptblock]{
|
||||||
|
|||||||
17
Headless/IntuneManagement.Headless.psd1
Normal file
17
Headless/IntuneManagement.Headless.psd1
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
@{
|
||||||
|
RootModule = 'IntuneManagement.Headless.psm1'
|
||||||
|
ModuleVersion = '0.1.0'
|
||||||
|
GUID = 'b5b4183d-8d6b-4b31-bbde-f2f0f0a0739d'
|
||||||
|
Author = 'OpenAI Codex'
|
||||||
|
Copyright = '(c) OpenAI. Adapter module for headless Intune policy migration.'
|
||||||
|
Description = 'Headless export/import wrapper for IntuneManagement.'
|
||||||
|
FunctionsToExport = @(
|
||||||
|
'Get-DefaultIntunePolicyObjectTypes',
|
||||||
|
'Export-IntunePolicies',
|
||||||
|
'Import-IntunePolicies',
|
||||||
|
'Invoke-IntunePolicyAction'
|
||||||
|
)
|
||||||
|
AliasesToExport = @()
|
||||||
|
VariablesToExport = @()
|
||||||
|
CmdletsToExport = @()
|
||||||
|
}
|
||||||
311
Headless/IntuneManagement.Headless.psm1
Normal file
311
Headless/IntuneManagement.Headless.psm1
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
function Get-DefaultIntunePolicyObjectTypes
|
||||||
|
{
|
||||||
|
@(
|
||||||
|
"DeviceConfiguration",
|
||||||
|
"SettingsCatalog",
|
||||||
|
"AdministrativeTemplates",
|
||||||
|
"CompliancePolicies",
|
||||||
|
"EndpointSecurity",
|
||||||
|
"PolicySets"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-IntuneManagementProjectRoot
|
||||||
|
{
|
||||||
|
Split-Path -Parent $PSScriptRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
function Resolve-HeadlessSettingsPath
|
||||||
|
{
|
||||||
|
param([string]$SettingsFile)
|
||||||
|
|
||||||
|
if($SettingsFile)
|
||||||
|
{
|
||||||
|
return $SettingsFile
|
||||||
|
}
|
||||||
|
|
||||||
|
Join-Path ([IO.Path]::GetTempPath()) "IntuneManagement.Settings.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-TemporaryBatchFile
|
||||||
|
{
|
||||||
|
param([string]$Prefix)
|
||||||
|
|
||||||
|
Join-Path ([IO.Path]::GetTempPath()) ("IntuneManagement.{0}.{1}.json" -f $Prefix, [guid]::NewGuid().ToString())
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-AuthParameters
|
||||||
|
{
|
||||||
|
param(
|
||||||
|
[string]$Secret,
|
||||||
|
[string]$Certificate
|
||||||
|
)
|
||||||
|
|
||||||
|
if((-not $Secret) -and (-not $Certificate))
|
||||||
|
{
|
||||||
|
throw "Specify -Secret or -Certificate."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-IntuneHeadlessBatch
|
||||||
|
{
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$TenantId,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$AppId,
|
||||||
|
|
||||||
|
[string]$Secret,
|
||||||
|
|
||||||
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[psobject]$BatchConfig,
|
||||||
|
|
||||||
|
[string]$SettingsFile,
|
||||||
|
|
||||||
|
[string]$BatchFile
|
||||||
|
)
|
||||||
|
|
||||||
|
Test-AuthParameters -Secret $Secret -Certificate $Certificate
|
||||||
|
|
||||||
|
$projectRoot = Get-IntuneManagementProjectRoot
|
||||||
|
$startScript = Join-Path $projectRoot "Start-IntuneManagement.ps1"
|
||||||
|
|
||||||
|
if(-not (Test-Path $startScript))
|
||||||
|
{
|
||||||
|
throw "Could not find Start-IntuneManagement.ps1 in $projectRoot"
|
||||||
|
}
|
||||||
|
|
||||||
|
$settingsPath = Resolve-HeadlessSettingsPath $SettingsFile
|
||||||
|
|
||||||
|
$deleteBatchFile = $false
|
||||||
|
if(-not $BatchFile)
|
||||||
|
{
|
||||||
|
$BatchFile = New-TemporaryBatchFile "Batch"
|
||||||
|
$deleteBatchFile = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$BatchConfig | ConvertTo-Json -Depth 20 | Out-File -LiteralPath $BatchFile -Encoding utf8 -Force
|
||||||
|
|
||||||
|
$invokeParams = @{
|
||||||
|
Silent = $true
|
||||||
|
JSonSettings = $true
|
||||||
|
JSonFile = $settingsPath
|
||||||
|
TenantId = $TenantId
|
||||||
|
AppId = $AppId
|
||||||
|
SilentBatchFile = $BatchFile
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Secret)
|
||||||
|
{
|
||||||
|
$invokeParams.Secret = $Secret
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$invokeParams.Certificate = $Certificate
|
||||||
|
}
|
||||||
|
|
||||||
|
& $startScript @invokeParams
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if($deleteBatchFile -and (Test-Path $BatchFile))
|
||||||
|
{
|
||||||
|
Remove-Item -LiteralPath $BatchFile -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Export-IntunePolicies
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$TenantId,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$AppId,
|
||||||
|
|
||||||
|
[string]$Secret,
|
||||||
|
|
||||||
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$ExportPath,
|
||||||
|
|
||||||
|
[string]$SettingsFile,
|
||||||
|
|
||||||
|
[string]$BatchFile,
|
||||||
|
|
||||||
|
[string]$NameFilter = "",
|
||||||
|
|
||||||
|
[string[]]$ObjectTypes = (Get-DefaultIntunePolicyObjectTypes),
|
||||||
|
|
||||||
|
[switch]$IncludeAssignments,
|
||||||
|
|
||||||
|
[switch]$AddCompanyName
|
||||||
|
)
|
||||||
|
|
||||||
|
$batchConfig = [PSCustomObject]@{
|
||||||
|
BulkExport = @(
|
||||||
|
[PSCustomObject]@{ Name = "txtExportPath"; Value = $ExportPath },
|
||||||
|
[PSCustomObject]@{ Name = "txtExportNameFilter"; Value = $NameFilter },
|
||||||
|
[PSCustomObject]@{ Name = "chkAddObjectType"; Value = $true },
|
||||||
|
[PSCustomObject]@{ Name = "chkExportAssignments"; Value = $IncludeAssignments.IsPresent },
|
||||||
|
[PSCustomObject]@{ Name = "chkAddCompanyName"; Value = $AddCompanyName.IsPresent },
|
||||||
|
[PSCustomObject]@{ Name = "ObjectTypes"; Type = "Custom"; ObjectTypes = @($ObjectTypes) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Invoke-IntuneHeadlessBatch `
|
||||||
|
-TenantId $TenantId `
|
||||||
|
-AppId $AppId `
|
||||||
|
-Secret $Secret `
|
||||||
|
-Certificate $Certificate `
|
||||||
|
-BatchConfig $batchConfig `
|
||||||
|
-SettingsFile $SettingsFile `
|
||||||
|
-BatchFile $BatchFile
|
||||||
|
}
|
||||||
|
|
||||||
|
function Import-IntunePolicies
|
||||||
|
{
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$TenantId,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$AppId,
|
||||||
|
|
||||||
|
[string]$Secret,
|
||||||
|
|
||||||
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$ImportPath,
|
||||||
|
|
||||||
|
[string]$SettingsFile,
|
||||||
|
|
||||||
|
[string]$BatchFile,
|
||||||
|
|
||||||
|
[string]$NameFilter = "",
|
||||||
|
|
||||||
|
[ValidateSet("alwaysImport","skipIfExist","replace","replace_with_assignments","update")]
|
||||||
|
[string]$ImportType = "alwaysImport",
|
||||||
|
|
||||||
|
[string[]]$ObjectTypes = (Get-DefaultIntunePolicyObjectTypes),
|
||||||
|
|
||||||
|
[switch]$IncludeAssignments,
|
||||||
|
|
||||||
|
[switch]$IncludeScopeTags,
|
||||||
|
|
||||||
|
[switch]$ReplaceDependencyIds
|
||||||
|
)
|
||||||
|
|
||||||
|
$batchConfig = [PSCustomObject]@{
|
||||||
|
BulkImport = @(
|
||||||
|
[PSCustomObject]@{ Name = "txtImportPath"; Value = $ImportPath },
|
||||||
|
[PSCustomObject]@{ Name = "txtImportNameFilter"; Value = $NameFilter },
|
||||||
|
[PSCustomObject]@{ Name = "chkAddObjectType"; Value = $true },
|
||||||
|
[PSCustomObject]@{ Name = "chkImportScopes"; Value = $IncludeScopeTags.IsPresent },
|
||||||
|
[PSCustomObject]@{ Name = "chkImportAssignments"; Value = $IncludeAssignments.IsPresent },
|
||||||
|
[PSCustomObject]@{ Name = "chkReplaceDependencyIDs"; Value = $ReplaceDependencyIds.IsPresent },
|
||||||
|
[PSCustomObject]@{ Name = "cbImportType"; Value = $ImportType },
|
||||||
|
[PSCustomObject]@{ Name = "ObjectTypes"; Type = "Custom"; ObjectTypes = @($ObjectTypes) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Invoke-IntuneHeadlessBatch `
|
||||||
|
-TenantId $TenantId `
|
||||||
|
-AppId $AppId `
|
||||||
|
-Secret $Secret `
|
||||||
|
-Certificate $Certificate `
|
||||||
|
-BatchConfig $batchConfig `
|
||||||
|
-SettingsFile $SettingsFile `
|
||||||
|
-BatchFile $BatchFile
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-IntunePolicyAction
|
||||||
|
{
|
||||||
|
[CmdletBinding(DefaultParameterSetName = 'Export')]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateSet("Export","Import")]
|
||||||
|
[string]$Action,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$TenantId,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$AppId,
|
||||||
|
|
||||||
|
[string]$Secret,
|
||||||
|
|
||||||
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[string]$SettingsFile,
|
||||||
|
|
||||||
|
[string]$BatchFile,
|
||||||
|
|
||||||
|
[string]$NameFilter = "",
|
||||||
|
|
||||||
|
[string[]]$ObjectTypes = (Get-DefaultIntunePolicyObjectTypes),
|
||||||
|
|
||||||
|
[string]$ExportPath,
|
||||||
|
|
||||||
|
[string]$ImportPath,
|
||||||
|
|
||||||
|
[ValidateSet("alwaysImport","skipIfExist","replace","replace_with_assignments","update")]
|
||||||
|
[string]$ImportType = "alwaysImport",
|
||||||
|
|
||||||
|
[switch]$IncludeAssignments,
|
||||||
|
|
||||||
|
[switch]$AddCompanyName,
|
||||||
|
|
||||||
|
[switch]$IncludeScopeTags,
|
||||||
|
|
||||||
|
[switch]$ReplaceDependencyIds
|
||||||
|
)
|
||||||
|
|
||||||
|
switch($Action)
|
||||||
|
{
|
||||||
|
"Export"
|
||||||
|
{
|
||||||
|
if(-not $ExportPath) { throw "Export requires -ExportPath." }
|
||||||
|
Export-IntunePolicies `
|
||||||
|
-TenantId $TenantId `
|
||||||
|
-AppId $AppId `
|
||||||
|
-Secret $Secret `
|
||||||
|
-Certificate $Certificate `
|
||||||
|
-ExportPath $ExportPath `
|
||||||
|
-SettingsFile $SettingsFile `
|
||||||
|
-BatchFile $BatchFile `
|
||||||
|
-NameFilter $NameFilter `
|
||||||
|
-ObjectTypes $ObjectTypes `
|
||||||
|
-IncludeAssignments:$IncludeAssignments `
|
||||||
|
-AddCompanyName:$AddCompanyName
|
||||||
|
}
|
||||||
|
"Import"
|
||||||
|
{
|
||||||
|
if(-not $ImportPath) { throw "Import requires -ImportPath." }
|
||||||
|
Import-IntunePolicies `
|
||||||
|
-TenantId $TenantId `
|
||||||
|
-AppId $AppId `
|
||||||
|
-Secret $Secret `
|
||||||
|
-Certificate $Certificate `
|
||||||
|
-ImportPath $ImportPath `
|
||||||
|
-SettingsFile $SettingsFile `
|
||||||
|
-BatchFile $BatchFile `
|
||||||
|
-NameFilter $NameFilter `
|
||||||
|
-ImportType $ImportType `
|
||||||
|
-ObjectTypes $ObjectTypes `
|
||||||
|
-IncludeAssignments:$IncludeAssignments `
|
||||||
|
-IncludeScopeTags:$IncludeScopeTags `
|
||||||
|
-ReplaceDependencyIds:$ReplaceDependencyIds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
Headless/README.md
Normal file
40
Headless/README.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# IntuneManagement Headless
|
||||||
|
|
||||||
|
This is the CLI-first surface for a cross-platform fork of the original IntuneManagement project.
|
||||||
|
|
||||||
|
The original project is still a Windows WPF application. This layer treats that codebase as an implementation backend and exposes a smaller product surface focused on:
|
||||||
|
|
||||||
|
* app-only authentication
|
||||||
|
* headless export/import
|
||||||
|
* macOS/Linux/Windows execution with `pwsh`
|
||||||
|
* automation and CI usage
|
||||||
|
|
||||||
|
## Entry points
|
||||||
|
|
||||||
|
* [Start-HeadlessIntune.ps1](/Users/avedelphina/Local/IntuneManagement/Start-HeadlessIntune.ps1)
|
||||||
|
* [Scripts/Export-Policies.ps1](/Users/avedelphina/Local/IntuneManagement/Scripts/Export-Policies.ps1)
|
||||||
|
* [Scripts/Import-Policies.ps1](/Users/avedelphina/Local/IntuneManagement/Scripts/Import-Policies.ps1)
|
||||||
|
* [Headless/IntuneManagement.Headless.psd1](/Users/avedelphina/Local/IntuneManagement/Headless/IntuneManagement.Headless.psd1)
|
||||||
|
|
||||||
|
## Default policy scope
|
||||||
|
|
||||||
|
The default object types are:
|
||||||
|
|
||||||
|
* `DeviceConfiguration`
|
||||||
|
* `SettingsCatalog`
|
||||||
|
* `AdministrativeTemplates`
|
||||||
|
* `CompliancePolicies`
|
||||||
|
* `EndpointSecurity`
|
||||||
|
* `PolicySets`
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
pwsh ./Start-HeadlessIntune.ps1 `
|
||||||
|
-Action Export `
|
||||||
|
-TenantId "<source-tenant-id>" `
|
||||||
|
-AppId "<app-id>" `
|
||||||
|
-Secret "<client-secret>" `
|
||||||
|
-ExportPath "/tmp/intune-export" `
|
||||||
|
-IncludeAssignments
|
||||||
|
```
|
||||||
134
README.md
134
README.md
@@ -1,4 +1,14 @@
|
|||||||
# IntuneManagement with PowerShell and WPF UI
|
# IntuneManagement
|
||||||
|
|
||||||
|
This repository now contains two usable surfaces:
|
||||||
|
|
||||||
|
* the original Windows WPF application
|
||||||
|
* a newer headless CLI-first surface for cross-platform export/import
|
||||||
|
|
||||||
|
The CLI-first fork shape starts here:
|
||||||
|
|
||||||
|
* [Start-HeadlessIntune.ps1](/Users/avedelphina/Local/IntuneManagement/Start-HeadlessIntune.ps1)
|
||||||
|
* [Headless/README.md](/Users/avedelphina/Local/IntuneManagement/Headless/README.md)
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://twitter.com/Micke_K_72">
|
<a href="https://twitter.com/Micke_K_72">
|
||||||
@@ -64,6 +74,128 @@ The tool will by default generate the files; `BulkExport.json` and `BulkImport.j
|
|||||||
|
|
||||||
The app authentication can either be passed on the command line or stored in the settings. Tennant Settings is required for multiple environments.
|
The app authentication can either be passed on the command line or stored in the settings. Tennant Settings is required for multiple environments.
|
||||||
|
|
||||||
|
### Headless use on macOS/Linux
|
||||||
|
|
||||||
|
The WPF UI is still Windows-only, but the **silent batch** mode can be used headlessly with `pwsh` on macOS/Linux.
|
||||||
|
|
||||||
|
For non-Windows use:
|
||||||
|
|
||||||
|
* Run `Start-IntuneManagement.ps1` with `-Silent`
|
||||||
|
* Use app-only authentication with `-TenantId`, `-AppId` and `-Secret` or `-Certificate`
|
||||||
|
* Use `-JSonSettings` and preferably specify `-JSonFile`
|
||||||
|
* Pass a batch configuration JSON with `-SilentBatchFile`
|
||||||
|
|
||||||
|
Common policy object type IDs:
|
||||||
|
|
||||||
|
* `DeviceConfiguration`
|
||||||
|
* `SettingsCatalog`
|
||||||
|
* `AdministrativeTemplates`
|
||||||
|
* `CompliancePolicies`
|
||||||
|
* `EndpointSecurity`
|
||||||
|
* `PolicySets`
|
||||||
|
* `ConditionalAccess`
|
||||||
|
|
||||||
|
**Example export batch file**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"BulkExport": [
|
||||||
|
{ "Name": "txtExportPath", "Value": "/tmp/intune-export" },
|
||||||
|
{ "Name": "txtExportNameFilter", "Value": "" },
|
||||||
|
{ "Name": "chkAddObjectType", "Value": true },
|
||||||
|
{ "Name": "chkExportAssignments", "Value": true },
|
||||||
|
{ "Name": "chkAddCompanyName", "Value": false },
|
||||||
|
{
|
||||||
|
"Name": "ObjectTypes",
|
||||||
|
"Type": "Custom",
|
||||||
|
"ObjectTypes": [
|
||||||
|
"DeviceConfiguration",
|
||||||
|
"SettingsCatalog",
|
||||||
|
"AdministrativeTemplates",
|
||||||
|
"CompliancePolicies",
|
||||||
|
"EndpointSecurity",
|
||||||
|
"PolicySets"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example export command**
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
pwsh ./Start-IntuneManagement.ps1 `
|
||||||
|
-Silent `
|
||||||
|
-JSonSettings -JSonFile "/tmp/intune-settings.json" `
|
||||||
|
-TenantId "<source-tenant-id>" `
|
||||||
|
-AppId "<app-id>" `
|
||||||
|
-Secret "<client-secret>" `
|
||||||
|
-SilentBatchFile "/tmp/BulkExport.json"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example import batch file**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"BulkImport": [
|
||||||
|
{ "Name": "txtImportPath", "Value": "/tmp/intune-export/SourceTenantName" },
|
||||||
|
{ "Name": "txtImportNameFilter", "Value": "" },
|
||||||
|
{ "Name": "chkAddObjectType", "Value": true },
|
||||||
|
{ "Name": "chkImportScopes", "Value": true },
|
||||||
|
{ "Name": "chkImportAssignments", "Value": true },
|
||||||
|
{ "Name": "chkReplaceDependencyIDs", "Value": true },
|
||||||
|
{ "Name": "cbImportType", "Value": "alwaysImport" },
|
||||||
|
{
|
||||||
|
"Name": "ObjectTypes",
|
||||||
|
"Type": "Custom",
|
||||||
|
"ObjectTypes": [
|
||||||
|
"DeviceConfiguration",
|
||||||
|
"SettingsCatalog",
|
||||||
|
"AdministrativeTemplates",
|
||||||
|
"CompliancePolicies",
|
||||||
|
"EndpointSecurity",
|
||||||
|
"PolicySets"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example import command**
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
pwsh ./Start-IntuneManagement.ps1 `
|
||||||
|
-Silent `
|
||||||
|
-JSonSettings -JSonFile "/tmp/intune-settings.json" `
|
||||||
|
-TenantId "<target-tenant-id>" `
|
||||||
|
-AppId "<app-id>" `
|
||||||
|
-Secret "<client-secret>" `
|
||||||
|
-SilentBatchFile "/tmp/BulkImport.json"
|
||||||
|
```
|
||||||
|
|
||||||
|
Wrapper scripts are also included:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
pwsh ./Scripts/Export-Policies.ps1 `
|
||||||
|
-TenantId "<source-tenant-id>" `
|
||||||
|
-AppId "<app-id>" `
|
||||||
|
-Secret "<client-secret>" `
|
||||||
|
-ExportPath "/tmp/intune-export" `
|
||||||
|
-IncludeAssignments
|
||||||
|
```
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
pwsh ./Scripts/Import-Policies.ps1 `
|
||||||
|
-TenantId "<target-tenant-id>" `
|
||||||
|
-AppId "<app-id>" `
|
||||||
|
-Secret "<client-secret>" `
|
||||||
|
-ImportPath "/tmp/intune-export/SourceTenantName" `
|
||||||
|
-ImportType alwaysImport `
|
||||||
|
-IncludeAssignments `
|
||||||
|
-IncludeScopeTags `
|
||||||
|
-ReplaceDependencyIds
|
||||||
|
```
|
||||||
|
|
||||||
**Command line example:**
|
**Command line example:**
|
||||||
|
|
||||||
Start-IntuneManagement.ps1 -Silent -TenantId "<*TenantID*>" -SilentBatchFile <*PathToFile*> [-AppId <*AppId*>] [-Secret <*Secret*> | -Certificate <*CertThumb*>]
|
Start-IntuneManagement.ps1 -Silent -TenantId "<*TenantID*>" -SilentBatchFile <*PathToFile*> [-AppId <*AppId*>] [-Secret <*Secret*> | -Certificate <*CertThumb*>]
|
||||||
|
|||||||
43
Scripts/Export-Policies.ps1
Normal file
43
Scripts/Export-Policies.ps1
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Headless Intune policy export wrapper for macOS/Linux/Windows.
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$TenantId,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$AppId,
|
||||||
|
|
||||||
|
[string]$Secret,
|
||||||
|
|
||||||
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$ExportPath,
|
||||||
|
|
||||||
|
[string]$SettingsFile,
|
||||||
|
|
||||||
|
[string]$BatchFile,
|
||||||
|
|
||||||
|
[string]$NameFilter = "",
|
||||||
|
|
||||||
|
[string[]]$ObjectTypes = @(
|
||||||
|
"DeviceConfiguration",
|
||||||
|
"SettingsCatalog",
|
||||||
|
"AdministrativeTemplates",
|
||||||
|
"CompliancePolicies",
|
||||||
|
"EndpointSecurity",
|
||||||
|
"PolicySets"
|
||||||
|
),
|
||||||
|
|
||||||
|
[switch]$IncludeAssignments,
|
||||||
|
|
||||||
|
[switch]$AddCompanyName
|
||||||
|
)
|
||||||
|
|
||||||
|
$modulePath = Join-Path (Split-Path -Parent $PSScriptRoot) "Headless/IntuneManagement.Headless.psd1"
|
||||||
|
Import-Module $modulePath -Force
|
||||||
|
|
||||||
|
Export-IntunePolicies @PSBoundParameters
|
||||||
48
Scripts/Import-Policies.ps1
Normal file
48
Scripts/Import-Policies.ps1
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Headless Intune policy import wrapper for macOS/Linux/Windows.
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$TenantId,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$AppId,
|
||||||
|
|
||||||
|
[string]$Secret,
|
||||||
|
|
||||||
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$ImportPath,
|
||||||
|
|
||||||
|
[string]$SettingsFile,
|
||||||
|
|
||||||
|
[string]$BatchFile,
|
||||||
|
|
||||||
|
[string]$NameFilter = "",
|
||||||
|
|
||||||
|
[ValidateSet("alwaysImport","skipIfExist","replace","replace_with_assignments","update")]
|
||||||
|
[string]$ImportType = "alwaysImport",
|
||||||
|
|
||||||
|
[string[]]$ObjectTypes = @(
|
||||||
|
"DeviceConfiguration",
|
||||||
|
"SettingsCatalog",
|
||||||
|
"AdministrativeTemplates",
|
||||||
|
"CompliancePolicies",
|
||||||
|
"EndpointSecurity",
|
||||||
|
"PolicySets"
|
||||||
|
),
|
||||||
|
|
||||||
|
[switch]$IncludeAssignments,
|
||||||
|
|
||||||
|
[switch]$IncludeScopeTags,
|
||||||
|
|
||||||
|
[switch]$ReplaceDependencyIds
|
||||||
|
)
|
||||||
|
|
||||||
|
$modulePath = Join-Path (Split-Path -Parent $PSScriptRoot) "Headless/IntuneManagement.Headless.psd1"
|
||||||
|
Import-Module $modulePath -Force
|
||||||
|
|
||||||
|
Import-IntunePolicies @PSBoundParameters
|
||||||
74
Start-HeadlessIntune.ps1
Normal file
74
Start-HeadlessIntune.ps1
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[ValidateSet("Export","Import")]
|
||||||
|
[string]$Action,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$TenantId,
|
||||||
|
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$AppId,
|
||||||
|
|
||||||
|
[string]$Secret,
|
||||||
|
|
||||||
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[string]$SettingsFile,
|
||||||
|
|
||||||
|
[string]$BatchFile,
|
||||||
|
|
||||||
|
[string]$NameFilter = "",
|
||||||
|
|
||||||
|
[string[]]$ObjectTypes,
|
||||||
|
|
||||||
|
[string]$ExportPath,
|
||||||
|
|
||||||
|
[string]$ImportPath,
|
||||||
|
|
||||||
|
[ValidateSet("alwaysImport","skipIfExist","replace","replace_with_assignments","update")]
|
||||||
|
[string]$ImportType = "alwaysImport",
|
||||||
|
|
||||||
|
[switch]$IncludeAssignments,
|
||||||
|
|
||||||
|
[switch]$AddCompanyName,
|
||||||
|
|
||||||
|
[switch]$IncludeScopeTags,
|
||||||
|
|
||||||
|
[switch]$ReplaceDependencyIds
|
||||||
|
)
|
||||||
|
|
||||||
|
$modulePath = Join-Path $PSScriptRoot "Headless/IntuneManagement.Headless.psd1"
|
||||||
|
Import-Module $modulePath -Force
|
||||||
|
|
||||||
|
$invokeParams = @{
|
||||||
|
Action = $Action
|
||||||
|
TenantId = $TenantId
|
||||||
|
AppId = $AppId
|
||||||
|
SettingsFile = $SettingsFile
|
||||||
|
BatchFile = $BatchFile
|
||||||
|
NameFilter = $NameFilter
|
||||||
|
ExportPath = $ExportPath
|
||||||
|
ImportPath = $ImportPath
|
||||||
|
ImportType = $ImportType
|
||||||
|
IncludeAssignments = $IncludeAssignments
|
||||||
|
AddCompanyName = $AddCompanyName
|
||||||
|
IncludeScopeTags = $IncludeScopeTags
|
||||||
|
ReplaceDependencyIds = $ReplaceDependencyIds
|
||||||
|
}
|
||||||
|
|
||||||
|
if($PSBoundParameters.ContainsKey("ObjectTypes"))
|
||||||
|
{
|
||||||
|
$invokeParams.ObjectTypes = $ObjectTypes
|
||||||
|
}
|
||||||
|
|
||||||
|
if($Secret)
|
||||||
|
{
|
||||||
|
$invokeParams.Secret = $Secret
|
||||||
|
}
|
||||||
|
elseif($Certificate)
|
||||||
|
{
|
||||||
|
$invokeParams.Certificate = $Certificate
|
||||||
|
}
|
||||||
|
|
||||||
|
Invoke-IntunePolicyAction @invokeParams
|
||||||
Reference in New Issue
Block a user