3.3.1 Beta
This commit is contained in:
@@ -14,11 +14,11 @@ Microsoft links:
|
|||||||
|
|
||||||
The **ADMX Import** tool is used for configuring 3rd party applications e.g. Chrome, Google Update etc., These ADMX files are available from the software vendor. An ADMX can be loaded in the tool and all settings can be configured using a similar UI as GPMC. When the ADMX is loaded, the script will look for an ADML file that is either in the same directory or in the en-US subdirectory. An ADML file can also be loaded manually, if another language should be used in the UI.
|
The **ADMX Import** tool is used for configuring 3rd party applications e.g. Chrome, Google Update etc., These ADMX files are available from the software vendor. An ADMX can be loaded in the tool and all settings can be configured using a similar UI as GPMC. When the ADMX is loaded, the script will look for an ADML file that is either in the same directory or in the en-US subdirectory. An ADML file can also be loaded manually, if another language should be used in the UI.
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/ADMXExample.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
The image above shows the the tool after the chrome.admx file was loaded. The tool supports delivering ADMX settings to HKLM (Computer Settings) and HKCU (User Settings). Categories will be added based on the Class attribute for each ADMX policy setting. The *All settings* category will display all the settings for the base category (Computer or User)
|
The image above shows the the tool after the chrome.admx file was loaded. The tool supports delivering ADMX settings to HKLM (Computer Settings) and HKCU (User Settings). Categories will be added based on the Class attribute for each ADMX policy setting. The *All settings* category will display all the settings for the base category (Computer or User)
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/ADMXSettingExample.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
A policy setting can either be edited via double-clicking an item or right-clicking and select Edit.
|
A policy setting can either be edited via double-clicking an item or right-clicking and select Edit.
|
||||||
|
|
||||||
@@ -26,13 +26,13 @@ The *Intune OMA-URI name* property specifies the name of the OMA-URI row in the
|
|||||||
|
|
||||||
A policy must be set to Enabled before any changes can be made. The *Policy* tab will list all possible settings for the policy. This could be a dropdown box, text box, check box, numeric up-down box etc. The script creates the controls based on the presentation settings in the ADML file. An ADML is not mandatory but the controls and the UI could cause unpredictive results. Always use the associated ADML for correctly generated controls.
|
A policy must be set to Enabled before any changes can be made. The *Policy* tab will list all possible settings for the policy. This could be a dropdown box, text box, check box, numeric up-down box etc. The script creates the controls based on the presentation settings in the ADML file. An ADML is not mandatory but the controls and the UI could cause unpredictive results. Always use the associated ADML for correctly generated controls.
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/ADMXSettingExampleOMAURI.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
The *OMA-URI Settings* tab contains the configured settings. This is the string that will be added to the enabled policy. This can be manually configure in case there is something that is not supported by the script. Do **NOT** add <enabled /> or <disabled /> to this text box. The script will add that automatically. If *Manual configuration* is checked, the script will upload the text as it is specified, including additional manual changes. If it is not checked, the script will generate the text when importing the profile. If manual configuration is added and then checkbox is cleared, those changes will be lost during the upload.
|
The *OMA-URI Settings* tab contains the configured settings. This is the string that will be added to the enabled policy. This can be manually configure in case there is something that is not supported by the script. Do **NOT** add <enabled /> or <disabled /> to this text box. The script will add that automatically. If *Manual configuration* is checked, the script will upload the text as it is specified, including additional manual changes. If it is not checked, the script will generate the text when importing the profile. If manual configuration is added and then checkbox is cleared, those changes will be lost during the upload.
|
||||||
|
|
||||||
The *XML Definition* tab contains the XML node for the ADMX policy. This is used for reference in case manual configuration is required.
|
The *XML Definition* tab contains the XML node for the ADMX policy. This is used for reference in case manual configuration is required.
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/ADMXImportSetting.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
The *Import* tab is used for creating the Custom Profile in Intune. The *Custom Profile Name* is mandatory and specifies the name of the profile.
|
The *Import* tab is used for creating the Custom Profile in Intune. The *Custom Profile Name* is mandatory and specifies the name of the profile.
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ The *Import* button will create the Custom Profile in Intune. There is no visual
|
|||||||
|
|
||||||
The **Reg Values** tool can be used to create registry values in HKLM and HKCU. This uses the same functionality as the ADMX Import tool; ADMX ingestion. The difference is that the Reg Values tool builds the ADMX file in the background based on the added registry values. There are some benefits of using this over a PowerShell script e.g. Intune will state if the registry keys were applied successfully and if a conflict or an error occurred.
|
The **Reg Values** tool can be used to create registry values in HKLM and HKCU. This uses the same functionality as the ADMX Import tool; ADMX ingestion. The difference is that the Reg Values tool builds the ADMX file in the background based on the added registry values. There are some benefits of using this over a PowerShell script e.g. Intune will state if the registry keys were applied successfully and if a conflict or an error occurred.
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/ADMXRegValuePolicy.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
The initial screen include the options of specifying the Custom Profile name and description. The *Policy type* can either be Policy or Preferences. See Known Issues and Limitations for more information about policy types.
|
The initial screen include the options of specifying the Custom Profile name and description. The *Policy type* can either be Policy or Preferences. See Known Issues and Limitations for more information about policy types.
|
||||||
|
|
||||||
@@ -82,39 +82,39 @@ The *Additional value settings* section has additional settings for a policy typ
|
|||||||
|
|
||||||
Example of setting registry values for a device and a user:
|
Example of setting registry values for a device and a user:
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/RegPolicyHKCU.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
Example of adding HKCU settings
|
Example of adding HKCU settings
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/RegPolicyHKLM.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
Example of adding HKLM settings
|
Example of adding HKLM settings
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/RegADMXFileContent.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
Example of generated ADMX file
|
Example of generated ADMX file
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/RegValueIntuneProfile.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
Example of the created Custom Profile created.
|
Example of the created Custom Profile created.
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/RegProfileADMXIngestion.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
Example of the OMA-URI row for ADMX ingestion for a custom registry value.
|
Example of the OMA-URI row for ADMX ingestion for a custom registry value.
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/RegProfileOMAURISetting.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
Example of the OMA-URI row for specifying the registry values to set.
|
Example of the OMA-URI row for specifying the registry values to set.
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/RegValuesHKCU.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
Example of the implemented HKCU settings for a user
|
Example of the implemented HKCU settings for a user
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/RegValuesHKLM.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
Example of the implemented HKLM settings for a device
|
Example of the implemented HKLM settings for a device
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/RegValuesHKLMList.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
Example of the List type implementation on a device
|
Example of the List type implementation on a device
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ The Policy CSP will create multiple registry values under HKLM\Software\Microsof
|
|||||||
|
|
||||||
The ADMXDefault part will contain each Category, with full path, specified in the ADMX file. This is why the AppID must be unique when using multiple versions of the same admx file since each of these files will have the same category IDs e.g. each Chrome version should be named based on the version like Chromev91.
|
The ADMXDefault part will contain each Category, with full path, specified in the ADMX file. This is why the AppID must be unique when using multiple versions of the same admx file since each of these files will have the same category IDs e.g. each Chrome version should be named based on the version like Chromev91.
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/RegADMXDefault.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
**Note:** If the same ADMX filename is used, the first file saved will win. It looks like Intune will not overwrite an existing ADMX file. That is why a unique name must be specified when different versions of the ADMX file is used.
|
**Note:** If the same ADMX filename is used, the first file saved will win. It looks like Intune will not overwrite an existing ADMX file. That is why a unique name must be specified when different versions of the ADMX file is used.
|
||||||
|
|
||||||
@@ -170,11 +170,11 @@ The CategoryPath is the full path to the category where the setting is defined.
|
|||||||
|
|
||||||
One registry key for each ADMX policy is created under the Provider path (PolicyManager\Provider\\<GUID>) . This includes the OME-URI settings configured in the Custom Profile.
|
One registry key for each ADMX policy is created under the Provider path (PolicyManager\Provider\\<GUID>) . This includes the OME-URI settings configured in the Custom Profile.
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/RegADMXProvider.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
Applied settings are added to the Current registry key, Current\Device or Current\\<SID> depending if it is for the device or the user. There is one key for each policy category.
|
Applied settings are added to the Current registry key, Current\Device or Current\\<SID> depending if it is for the device or the user. There is one key for each policy category.
|
||||||
|
|
||||||

|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/RegADMXCurrent.png" height="50%" width="50%"/>
|
||||||
|
|
||||||
**Troubleshooting**
|
**Troubleshooting**
|
||||||
|
|
||||||
|
|||||||
295
Core.psm1
295
Core.psm1
@@ -11,7 +11,7 @@ This module handles the WPF UI
|
|||||||
|
|
||||||
function Get-ModuleVersion
|
function Get-ModuleVersion
|
||||||
{
|
{
|
||||||
'3.3.0'
|
'3.3.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
function Start-CoreApp
|
function Start-CoreApp
|
||||||
@@ -28,6 +28,7 @@ function Start-CoreApp
|
|||||||
|
|
||||||
$global:loadedModules = @()
|
$global:loadedModules = @()
|
||||||
$global:viewObjects = @()
|
$global:viewObjects = @()
|
||||||
|
$script:LogItems = [System.Collections.ObjectModel.ObservableCollection[object]]::new()
|
||||||
|
|
||||||
$global:AppRootFolder = $PSScriptRoot
|
$global:AppRootFolder = $PSScriptRoot
|
||||||
|
|
||||||
@@ -70,6 +71,19 @@ function Start-CoreApp
|
|||||||
|
|
||||||
Invoke-ModuleFunction "Invoke-InitializeModule"
|
Invoke-ModuleFunction "Invoke-InitializeModule"
|
||||||
|
|
||||||
|
#Add menu group and items
|
||||||
|
$script:LogViewObject = (New-Object PSObject -Property @{
|
||||||
|
Title = "Log"
|
||||||
|
Description = "View log items"
|
||||||
|
ID = "CoreLog"
|
||||||
|
HideMenu = $true
|
||||||
|
Activating = { Show-LogView }
|
||||||
|
Permissions = @()
|
||||||
|
ViewPanel = $null
|
||||||
|
})
|
||||||
|
|
||||||
|
Add-ViewObject $script:LogViewObject
|
||||||
|
|
||||||
#This will load the main window
|
#This will load the main window
|
||||||
$global:txtSplashText.Text = "Load main window"
|
$global:txtSplashText.Text = "Load main window"
|
||||||
[System.Windows.Forms.Application]::DoEvents()
|
[System.Windows.Forms.Application]::DoEvents()
|
||||||
@@ -175,16 +189,27 @@ function Write-Log
|
|||||||
if($type -eq 2)
|
if($type -eq 2)
|
||||||
{
|
{
|
||||||
Write-Warning $Text
|
Write-Warning $Text
|
||||||
|
$typeStr = "Error"
|
||||||
}
|
}
|
||||||
elseif($type -eq 3)
|
elseif($type -eq 3)
|
||||||
{
|
{
|
||||||
$host.ui.WriteErrorLine($Text)
|
$host.ui.WriteErrorLine($Text)
|
||||||
|
$typeStr = "Warning"
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
write-host $Text
|
write-host $Text
|
||||||
|
$typeStr = "Info"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$script:LogItems.Add([PSCustomObject]@{
|
||||||
|
ID = ($script:LogItems.Count + 1)
|
||||||
|
DateTime = $date
|
||||||
|
Type = $type
|
||||||
|
TypeText = $typeStr
|
||||||
|
Text = $Text
|
||||||
|
})
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out-file -filePath $global:logFile -append -encoding "ASCII" -inputObject $logOut
|
out-file -filePath $global:logFile -append -encoding "ASCII" -inputObject $logOut
|
||||||
@@ -890,7 +915,7 @@ function Save-Setting
|
|||||||
{
|
{
|
||||||
if($SubPath)
|
if($SubPath)
|
||||||
{
|
{
|
||||||
$arrParts = $SubPath.Split(@('/','\'))
|
$arrParts = $SubPath.TrimEnd(@('/','\')).Split(@('/','\'))
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -901,13 +926,15 @@ function Save-Setting
|
|||||||
|
|
||||||
foreach($part in $arrParts)
|
foreach($part in $arrParts)
|
||||||
{
|
{
|
||||||
|
if(-not $part.Trim()) { continue }
|
||||||
|
|
||||||
if(($parentSetting.PSObject.Properties | Where Name -eq $part))
|
if(($parentSetting.PSObject.Properties | Where Name -eq $part))
|
||||||
{
|
{
|
||||||
$parentSetting = $parentSetting.$part
|
$parentSetting = $parentSetting.$part
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$parentSetting.$part = @()
|
$parentSetting | Add-Member -MemberType NoteProperty -Name $part -Value ([PSCustomObject]@{})
|
||||||
$parentSetting = $parentSetting.$part
|
$parentSetting = $parentSetting.$part
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -978,7 +1005,7 @@ function Get-Setting
|
|||||||
{
|
{
|
||||||
if($SubPath)
|
if($SubPath)
|
||||||
{
|
{
|
||||||
$arrParts = $SubPath.Split(@('/','\'))
|
$arrParts = $SubPath.TrimEnd(@('/','\')).Split(@('/','\'))
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1119,6 +1146,111 @@ function Add-RegKeyToSettings
|
|||||||
Write-LogError "Failed to add reg keys to json settings" $_.Exception
|
Write-LogError "Failed to add reg keys to json settings" $_.Exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Remove-TenantSetting
|
||||||
|
{
|
||||||
|
param($settingValue)
|
||||||
|
|
||||||
|
$subPath = ($global:Organization.Id + "\" + $settingValue.SubPath)
|
||||||
|
|
||||||
|
if($global:JsonSettingsObj)
|
||||||
|
{
|
||||||
|
if($SubPath)
|
||||||
|
{
|
||||||
|
$arrParts = $SubPath.TrimEnd(@('/','\')).Split(@('/','\'))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$arrParts = @()
|
||||||
|
}
|
||||||
|
|
||||||
|
$parentSetting = $global:JsonSettingsObj
|
||||||
|
|
||||||
|
foreach($part in $arrParts)
|
||||||
|
{
|
||||||
|
if(($parentSetting.PSObject.Properties | Where Name -eq $part))
|
||||||
|
{
|
||||||
|
$parentSetting = $parentSetting.$part
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(($parentSetting.PSObject.Properties | Where Name -eq $settingValue.Key))
|
||||||
|
{
|
||||||
|
$parentSetting.PSObject.Properties.Remove($settingValue.Key)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$regPath = Get-RegPath $subPath
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$temp = Get-Item -LiteralPath $regPath -ErrorAction SilentlyContinue
|
||||||
|
if(($temp.Property -contains $settingValue.Key))
|
||||||
|
{
|
||||||
|
Remove-ItemProperty -Path $regPath -Name $settingValue.Key -Force -ErrorAction Stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Write-LogError "Failed to remove reg value: $($settingValue.Key) in key $($regPath)" $_.Exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-IsTenantSettingConfigured
|
||||||
|
{
|
||||||
|
param($settingValue)
|
||||||
|
|
||||||
|
$subPath = ($global:Organization.Id + "\" + $settingValue.SubPath)
|
||||||
|
|
||||||
|
if($global:JsonSettingsObj)
|
||||||
|
{
|
||||||
|
if($SubPath)
|
||||||
|
{
|
||||||
|
$arrParts = $SubPath.TrimEnd(@('/','\')).Split(@('/','\'))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$arrParts = @()
|
||||||
|
}
|
||||||
|
|
||||||
|
$parentSetting = $global:JsonSettingsObj
|
||||||
|
|
||||||
|
foreach($part in $arrParts)
|
||||||
|
{
|
||||||
|
if(($parentSetting.PSObject.Properties | Where Name -eq $part))
|
||||||
|
{
|
||||||
|
$parentSetting = $parentSetting.$part
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($null -ne ($parentSetting.PSObject.Properties | Where Name -eq $settingValue.Key))
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$regPath = Get-RegPath $subPath
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$temp = Get-Item -LiteralPath $regPath -ErrorAction Stop
|
||||||
|
return ($temp.GetValueNames() -contains $settingValue.Key)
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $false
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Setting functions
|
#region Setting functions
|
||||||
@@ -1131,33 +1263,54 @@ function Add-RegKeyToSettings
|
|||||||
|
|
||||||
function Add-SettingsItem
|
function Add-SettingsItem
|
||||||
{
|
{
|
||||||
param($settingItem, $title, $description)
|
param($settingItem, $settingValue)
|
||||||
|
|
||||||
$rd = [System.Windows.Controls.RowDefinition]::new()
|
$rd = [System.Windows.Controls.RowDefinition]::new()
|
||||||
$rd.Height = [double]::NaN
|
$rd.Height = [double]::NaN
|
||||||
$spSettings.RowDefinitions.Add($rd)
|
$spSettings.RowDefinitions.Add($rd)
|
||||||
$settingItem.SetValue([System.Windows.Controls.Grid]::RowProperty,$spSettings.RowDefinitions.Count-1)
|
$settingItem.SetValue([System.Windows.Controls.Grid]::RowProperty,$spSettings.RowDefinitions.Count-1)
|
||||||
|
|
||||||
if(-not $title)
|
if(-not $settingValue)
|
||||||
{
|
{
|
||||||
$settingItem.SetValue([System.Windows.Controls.Grid]::ColumnSpanProperty, 2)
|
$settingItem.SetValue([System.Windows.Controls.Grid]::ColumnSpanProperty, 99)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if($description)
|
if($settingValue.Description)
|
||||||
{
|
{
|
||||||
$descriptionInfo = "<Rectangle Style=`"{DynamicResource InfoIcon}`" ToolTip=`"$($description)`" Margin=`"5,0,0,0`" />"
|
$descriptionInfo = "<Rectangle Style=`"{DynamicResource InfoIcon}`" ToolTip=`"$($settingValue.Description)`" Margin=`"5,0,0,0`" />"
|
||||||
}
|
}
|
||||||
|
|
||||||
$xaml = @"
|
$xaml = @"
|
||||||
<StackPanel $wpfNS Orientation="Horizontal" Margin="5,5,5,0">
|
<StackPanel $wpfNS Orientation="Horizontal" Margin="5,5,5,0">
|
||||||
<TextBlock Text="$($title)" VerticalAlignment="Center"/>
|
<TextBlock Text="$($settingValue.Title)" VerticalAlignment="Center"/>
|
||||||
$descriptionInfo
|
$descriptionInfo
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
"@
|
"@
|
||||||
|
|
||||||
|
if($script:tenantSettings -and $settingValue)
|
||||||
|
{
|
||||||
|
#_IsChecked
|
||||||
|
$tenantConfig = [System.Windows.Controls.CheckBox]::new()
|
||||||
|
$tenantConfig.ToolTip = "Enable tenant specific setting"
|
||||||
|
$tenantConfig.SetValue([System.Windows.Controls.Grid]::RowProperty,$spSettings.RowDefinitions.Count-1)
|
||||||
|
$tenantConfig.SetValue([System.Windows.Controls.Grid]::ColumnProperty, 0)
|
||||||
|
$tenantConfig.Margin = "0,5,0,0"
|
||||||
|
$tenantConfig.Tag = $settingValue
|
||||||
|
$tenantConfig.IsChecked = (Get-IsTenantSettingConfigured $settingValue)
|
||||||
|
$settingItem.IsEnabled = $tenantConfig.IsChecked
|
||||||
|
$tenantConfig.add_Click({
|
||||||
|
if($this.Tag.Control) { $this.Tag.Control.IsEnabled = $this.IsChecked }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
$spSettings.AddChild($tenantConfig)
|
||||||
|
}
|
||||||
|
|
||||||
$settingsTitle = [Windows.Markup.XamlReader]::Parse($xaml)
|
$settingsTitle = [Windows.Markup.XamlReader]::Parse($xaml)
|
||||||
$settingsTitle.SetValue([System.Windows.Controls.Grid]::RowProperty,$spSettings.RowDefinitions.Count-1)
|
$settingsTitle.SetValue([System.Windows.Controls.Grid]::RowProperty,$spSettings.RowDefinitions.Count-1)
|
||||||
$settingItem.SetValue([System.Windows.Controls.Grid]::ColumnProperty, 1)
|
$settingsTitle.SetValue([System.Windows.Controls.Grid]::ColumnProperty, 1)
|
||||||
|
|
||||||
|
$settingItem.SetValue([System.Windows.Controls.Grid]::ColumnProperty, 2)
|
||||||
$spSettings.AddChild($settingsTitle)
|
$spSettings.AddChild($settingsTitle)
|
||||||
$settingItem.Margin = "0,5,0,0"
|
$settingItem.Margin = "0,5,0,0"
|
||||||
}
|
}
|
||||||
@@ -1244,7 +1397,16 @@ function Add-SettingValue
|
|||||||
|
|
||||||
$id = "id_" + [Guid]::NewGuid().ToString('n')
|
$id = "id_" + [Guid]::NewGuid().ToString('n')
|
||||||
|
|
||||||
$value = Get-SettingValue $settingValue.Key
|
if($settingValue.TenantSettings -eq $false -and $script:tenantSettings)
|
||||||
|
{
|
||||||
|
return # Value nut supported in Tenant Settings
|
||||||
|
}
|
||||||
|
elseif($settingValue.GlobalSettings -eq $false -and $script:tenantSettings -ne $true)
|
||||||
|
{
|
||||||
|
return # Value nut supported in Global Settings
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = Get-SettingValue $settingValue.Key -GlobalOnly:($script:tenantSettings -ne $true)
|
||||||
|
|
||||||
if($settingValue.Type -eq "folder")
|
if($settingValue.Type -eq "folder")
|
||||||
{
|
{
|
||||||
@@ -1265,7 +1427,7 @@ function Add-SettingValue
|
|||||||
|
|
||||||
if($settingObj)
|
if($settingObj)
|
||||||
{
|
{
|
||||||
Add-SettingsItem $settingObj $settingValue.Title $settingValue.Description
|
Add-SettingsItem $settingObj $settingValue
|
||||||
# Find the control in the setting object that contains the actual value
|
# Find the control in the setting object that contains the actual value
|
||||||
# $settingObj might be a grid that contains the TextBox with the settings value
|
# $settingObj might be a grid that contains the TextBox with the settings value
|
||||||
$ctrl = $settingObj.FindName($id)
|
$ctrl = $settingObj.FindName($id)
|
||||||
@@ -1294,21 +1456,25 @@ function Add-SettingTitle
|
|||||||
|
|
||||||
function Show-SettingsForm
|
function Show-SettingsForm
|
||||||
{
|
{
|
||||||
|
param([switch]$Tenant)
|
||||||
|
|
||||||
$settingsStr = Get-Content ($global:AppRootFolder+ "\Xaml\SettingsForm.xaml")
|
$settingsStr = Get-Content ($global:AppRootFolder+ "\Xaml\SettingsForm.xaml")
|
||||||
|
|
||||||
$settingsForm = [Windows.Markup.XamlReader]::Parse($settingsStr)
|
$settingsForm = [Windows.Markup.XamlReader]::Parse($settingsStr)
|
||||||
$global:settingControls = @()
|
$global:settingControls = @()
|
||||||
$global:spSettings = $settingsForm.FindName("spSettings")
|
$global:spSettings = $settingsForm.FindName("spSettings")
|
||||||
|
|
||||||
|
$script:tenantSettings = ($Tenant -eq $true)
|
||||||
Add-XamlEvent $settingsForm "btnSave" "Add_Click" ({
|
Add-XamlEvent $settingsForm "btnSave" "Add_Click" ({
|
||||||
Save-AllSettings
|
Save-AllSettings
|
||||||
})
|
})
|
||||||
|
|
||||||
Add-XamlEvent $settingsForm "btnClose" "Add_Click" ({
|
Add-XamlEvent $settingsForm "btnClose" "Add_Click" ({
|
||||||
|
$script:tenantSettings = $null
|
||||||
Show-ModalObject
|
Show-ModalObject
|
||||||
})
|
})
|
||||||
|
|
||||||
if($JsonSettingsObj)
|
if($JsonSettingsObj -or $script:tenantSettings -eq $true)
|
||||||
{
|
{
|
||||||
Set-XamlProperty $settingsForm "btnExport" "Visibility" "Collapsed"
|
Set-XamlProperty $settingsForm "btnExport" "Visibility" "Collapsed"
|
||||||
}
|
}
|
||||||
@@ -1387,6 +1553,14 @@ function Add-DefaultSettings
|
|||||||
DefaultValue = $false
|
DefaultValue = $false
|
||||||
}) "General"
|
}) "General"
|
||||||
|
|
||||||
|
Add-SettingsObject (New-Object PSObject -Property @{
|
||||||
|
Title = "Hide No-access items"
|
||||||
|
Key = "HideNoAccess"
|
||||||
|
Type = "Boolean"
|
||||||
|
Description="Remove items from the menu if object permissions is missing. Default is to mark them with red"
|
||||||
|
DefaultValue = $false
|
||||||
|
}) "General"
|
||||||
|
|
||||||
Add-SettingsObject (New-Object PSObject -Property @{
|
Add-SettingsObject (New-Object PSObject -Property @{
|
||||||
Title = "Preview"
|
Title = "Preview"
|
||||||
Key = "PreviewFeatures"
|
Key = "PreviewFeatures"
|
||||||
@@ -1412,11 +1586,20 @@ function Add-SettingsObject
|
|||||||
function Save-AllSettings
|
function Save-AllSettings
|
||||||
{
|
{
|
||||||
Write-Status "Save settings"
|
Write-Status "Save settings"
|
||||||
|
$dt1 = Get-Date
|
||||||
|
$curHideNoAccess = Get-SettingValue "HideNoAccess"
|
||||||
|
|
||||||
foreach($section in $global:appSettingSections)
|
foreach($section in $global:appSettingSections)
|
||||||
{
|
{
|
||||||
foreach($settingObj in $section.Values)
|
foreach($settingObj in $section.Values)
|
||||||
{
|
{
|
||||||
if(-not $settingObj.Control) { continue }
|
if(-not $settingObj.Control) { continue }
|
||||||
|
if($settingObj.Control.IsEnabled -eq $false -and $script:tenantSettings)
|
||||||
|
{
|
||||||
|
Remove-TenantSetting $settingObj
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
$valueFound = $false
|
$valueFound = $false
|
||||||
if($settingObj.Control.GetType().Name -eq "TextBox")
|
if($settingObj.Control.GetType().Name -eq "TextBox")
|
||||||
{
|
{
|
||||||
@@ -1456,7 +1639,15 @@ function Save-AllSettings
|
|||||||
|
|
||||||
if($valueFound)
|
if($valueFound)
|
||||||
{
|
{
|
||||||
Save-Setting $settingObj.SubPath $settingObj.Key $value
|
if($script:tenantSettings)
|
||||||
|
{
|
||||||
|
$subPath = ($global:Organization.Id + "\" + $settingObj.SubPath)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$subPath = $settingObj.SubPath
|
||||||
|
}
|
||||||
|
Save-Setting $subPath $settingObj.Key $value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1468,13 +1659,22 @@ function Save-AllSettings
|
|||||||
|
|
||||||
Initialize-Settings -Updated
|
Initialize-Settings -Updated
|
||||||
|
|
||||||
|
$newHideNoAccess = Get-SettingValue "HideNoAccess"
|
||||||
|
if($curHideNoAccess -ne $newHideNoAccess )
|
||||||
|
{
|
||||||
|
Show-ViewMenu
|
||||||
|
}
|
||||||
|
|
||||||
|
if($dt1.AddSeconds(1) -lt (Get-Date))
|
||||||
|
{
|
||||||
Start-Sleep -Seconds 1 # It goes to quick...ToDo: Do this in a better way
|
Start-Sleep -Seconds 1 # It goes to quick...ToDo: Do this in a better way
|
||||||
|
}
|
||||||
Write-Status ""
|
Write-Status ""
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-SettingValue
|
function Get-SettingValue
|
||||||
{
|
{
|
||||||
param($Key, $defaultValue)
|
param($Key, $defaultValue, [switch]$GlobalOnly, [switch]$TenantOnly, $TenantID)
|
||||||
|
|
||||||
foreach($section in $global:appSettingSections)
|
foreach($section in $global:appSettingSections)
|
||||||
{
|
{
|
||||||
@@ -1484,7 +1684,21 @@ function Get-SettingValue
|
|||||||
|
|
||||||
if(-not $defaultValue) { $defaultValue = $settingObj.DefaultValue }
|
if(-not $defaultValue) { $defaultValue = $settingObj.DefaultValue }
|
||||||
|
|
||||||
|
$value = $null
|
||||||
|
if(-not $TenantID) { $TenantID = $global:Organization.Id}
|
||||||
|
|
||||||
|
if($GlobalOnly -ne $true -and $TenantID)
|
||||||
|
{
|
||||||
|
# Try get Tenant specific value first
|
||||||
|
$value = Get-Setting ($TenantID + "\" + $settingObj.SubPath) $settingObj.Key
|
||||||
|
}
|
||||||
|
|
||||||
|
if($null -eq $value -and $TenantOnly -ne $true)
|
||||||
|
{
|
||||||
|
# Get global setting value if tenant value was not found
|
||||||
$value = Get-Setting $settingObj.SubPath $settingObj.Key $defaultValue
|
$value = Get-Setting $settingObj.SubPath $settingObj.Key $defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
if($value)
|
if($value)
|
||||||
{
|
{
|
||||||
if($settingObj.Type -eq "Boolean")
|
if($settingObj.Type -eq "Boolean")
|
||||||
@@ -1609,12 +1823,10 @@ function Show-View
|
|||||||
|
|
||||||
$global:currentViewObject = $viewObject
|
$global:currentViewObject = $viewObject
|
||||||
|
|
||||||
$viewItems = ?: ($viewObject.ViewInfo.Sort -ne $false) ($viewObject.ViewItems | Sort-Object -Property Title) ($viewObject.ViewItems)
|
Show-ViewMenu
|
||||||
|
|
||||||
$lblMenuTitle.Content = $viewObject.ViewInfo.Title
|
$lblMenuTitle.Content = $viewObject.ViewInfo.Title
|
||||||
|
|
||||||
$lstMenuItems.ItemsSource = @($viewItems)
|
|
||||||
|
|
||||||
$grdViewPanel.Children.Clear()
|
$grdViewPanel.Children.Clear()
|
||||||
|
|
||||||
if($viewObject.ViewInfo.Authenticate)
|
if($viewObject.ViewInfo.Authenticate)
|
||||||
@@ -1639,6 +1851,15 @@ function Show-View
|
|||||||
|
|
||||||
Show-AuthenticationInfo
|
Show-AuthenticationInfo
|
||||||
|
|
||||||
|
if($viewObject.ViewInfo.HideMenu -eq $true)
|
||||||
|
{
|
||||||
|
$global:grdViewItemMenu.Visibility = "Collapsed"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$global:grdViewItemMenu.Visibility = "Visible"
|
||||||
|
}
|
||||||
|
|
||||||
if($viewObject.ViewInfo.Activated)
|
if($viewObject.ViewInfo.Activated)
|
||||||
{
|
{
|
||||||
Write-Log "Activated View $($viewObject.ViewInfo.Title)"
|
Write-Log "Activated View $($viewObject.ViewInfo.Title)"
|
||||||
@@ -1648,6 +1869,20 @@ function Show-View
|
|||||||
Invoke-ModuleFunction "Invoke-ViewActivated"
|
Invoke-ModuleFunction "Invoke-ViewActivated"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Show-ViewMenu
|
||||||
|
{
|
||||||
|
$viewObject = $global:currentViewObject
|
||||||
|
|
||||||
|
$viewItems = ?: ($viewObject.ViewInfo.Sort -ne $false) ($viewObject.ViewItems | Sort-Object -Property Title) ($viewObject.ViewItems)
|
||||||
|
|
||||||
|
if((Get-SettingValue "HideNoAccess"))
|
||||||
|
{
|
||||||
|
$viewItems = $viewItems | Where { $_."@HasPermissions" -ne $false }
|
||||||
|
}
|
||||||
|
|
||||||
|
$lstMenuItems.ItemsSource = @($viewItems)
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Main Window
|
#region Main Window
|
||||||
@@ -1692,6 +1927,7 @@ function Get-MainWindow
|
|||||||
|
|
||||||
# ToDo: Convert to a list for data binding
|
# ToDo: Convert to a list for data binding
|
||||||
Add-XamlEvent $window "mnuSettings" "Add_Click" -scriptBlock ([scriptblock]{ Show-SettingsForm })
|
Add-XamlEvent $window "mnuSettings" "Add_Click" -scriptBlock ([scriptblock]{ Show-SettingsForm })
|
||||||
|
Add-XamlEvent $window "mnuTenantSettings" "Add_Click" -scriptBlock ([scriptblock]{ Show-SettingsForm -Tenant })
|
||||||
Add-XamlEvent $window "mnuUpdates" "Add_Click" -scriptBlock ([scriptblock]{ Show-UpdatesDialog })
|
Add-XamlEvent $window "mnuUpdates" "Add_Click" -scriptBlock ([scriptblock]{ Show-UpdatesDialog })
|
||||||
Add-XamlEvent $window "mnuAbout" "Add_Click" -scriptBlock ([scriptblock]{ Show-AboutDialog })
|
Add-XamlEvent $window "mnuAbout" "Add_Click" -scriptBlock ([scriptblock]{ Show-AboutDialog })
|
||||||
Add-XamlEvent $window "mnuExit" "Add_Click" -scriptBlock ([scriptblock]{
|
Add-XamlEvent $window "mnuExit" "Add_Click" -scriptBlock ([scriptblock]{
|
||||||
@@ -1962,6 +2198,27 @@ function Format-XML
|
|||||||
$StringWriter.ToString()
|
$StringWriter.ToString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Show-LogView
|
||||||
|
{
|
||||||
|
if($script:LogViewObject -and -not $script:LogViewObject.ViewPanel)
|
||||||
|
{
|
||||||
|
$viewPanel = Get-XamlObject ($global:AppRootFolder + "\Xaml\LogInfo.xaml")
|
||||||
|
|
||||||
|
if(-not $viewPanel) { return }
|
||||||
|
|
||||||
|
$script:LogViewObject.ViewPanel = $viewPanel
|
||||||
|
|
||||||
|
Set-XamlProperty $viewPanel "dgLogInfo" "ItemsSource" $script:LogItems
|
||||||
|
|
||||||
|
Add-XamlEvent $viewPanel "dgLogInfo" "add_selectionChanged" ({
|
||||||
|
$obj = $this.Parent.FindName("txtLogInfo")
|
||||||
|
if($obj)
|
||||||
|
{
|
||||||
|
$obj.Parent.DataContext = $this.SelectedValue
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
New-Alias -Name ?? -value Invoke-Coalesce
|
New-Alias -Name ?? -value Invoke-Coalesce
|
||||||
New-Alias -Name ?: -value Invoke-IfTrue
|
New-Alias -Name ?: -value Invoke-IfTrue
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ This module will also document some objects based on PowerShell functions
|
|||||||
|
|
||||||
function Get-ModuleVersion
|
function Get-ModuleVersion
|
||||||
{
|
{
|
||||||
'1.0.5'
|
'1.0.6'
|
||||||
}
|
}
|
||||||
|
|
||||||
function Invoke-InitializeModule
|
function Invoke-InitializeModule
|
||||||
@@ -1061,6 +1061,16 @@ function Add-CDDocumentCustomProfileProperty
|
|||||||
$obj | Add-Member Noteproperty -Name "detectionScriptAdded" -Value (-not [String]::IsNullOrEmpty($obj.detectionScriptContent))
|
$obj | Add-Member Noteproperty -Name "detectionScriptAdded" -Value (-not [String]::IsNullOrEmpty($obj.detectionScriptContent))
|
||||||
$obj | Add-Member Noteproperty -Name "remediationScriptAdded" -Value (-not [String]::IsNullOrEmpty($obj.remediationScriptContent))
|
$obj | Add-Member Noteproperty -Name "remediationScriptAdded" -Value (-not [String]::IsNullOrEmpty($obj.remediationScriptContent))
|
||||||
$obj | Add-Member Noteproperty -Name "useLoggedOnCredentials" -Value ($obj.runAsAccount -ne "system")
|
$obj | Add-Member Noteproperty -Name "useLoggedOnCredentials" -Value ($obj.runAsAccount -ne "system")
|
||||||
|
|
||||||
|
if($obj.detectionScriptContent)
|
||||||
|
{
|
||||||
|
$obj | Add-Member Noteproperty -Name "detectionScriptContentString" -Value ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String(($obj.detectionScriptContent))))
|
||||||
|
}
|
||||||
|
if($obj.remediationScriptContent)
|
||||||
|
{
|
||||||
|
$obj | Add-Member Noteproperty -Name "remediationScriptContentString" -Value ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String(($obj.remediationScriptContent))))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(($obj.PSObject.Properties | where Name -eq "securityRequireSafetyNetAttestationBasicIntegrity") -and
|
if(($obj.PSObject.Properties | where Name -eq "securityRequireSafetyNetAttestationBasicIntegrity") -and
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#https://docs.microsoft.com/en-us/office/vba/api/overview/word
|
#https://docs.microsoft.com/en-us/office/vba/api/overview/word
|
||||||
function Get-ModuleVersion
|
function Get-ModuleVersion
|
||||||
{
|
{
|
||||||
'1.0.5'
|
'1.0.6'
|
||||||
}
|
}
|
||||||
|
|
||||||
function Invoke-InitializeModule
|
function Invoke-InitializeModule
|
||||||
@@ -86,6 +86,10 @@ function Add-WordOptionsControl
|
|||||||
$global:txtWordTitleProperty.Text = Get-Setting "Documentation" "WordTitleProperty" "Intune documentation"
|
$global:txtWordTitleProperty.Text = Get-Setting "Documentation" "WordTitleProperty" "Intune documentation"
|
||||||
$global:txtWordSubjectProperty.Text = Get-Setting "Documentation" "WordSubjectProperty" "Intune documentation"
|
$global:txtWordSubjectProperty.Text = Get-Setting "Documentation" "WordSubjectProperty" "Intune documentation"
|
||||||
|
|
||||||
|
$global:chkWordIncludeScripts.IsChecked = ((Get-Setting "Documentation" "WordIncludeScripts" "true") -ne "false")
|
||||||
|
$global:chkWordExcludeScriptSignature.IsChecked = ((Get-Setting "Documentation" "WordExcludeScriptSignature" "false") -ne "false")
|
||||||
|
$global:txtWordScriptTableStyle.Text = Get-Setting "Documentation" "WordScriptTableStyle" ""
|
||||||
|
$global:txtWordScriptStyle.Text = Get-Setting "Documentation" "WordScriptStyle"
|
||||||
|
|
||||||
$global:chkWordOpenDocument.IsChecked = ((Get-Setting "Documentation" "WordOpenDocument" "true") -ne "false")
|
$global:chkWordOpenDocument.IsChecked = ((Get-Setting "Documentation" "WordOpenDocument" "true") -ne "false")
|
||||||
|
|
||||||
@@ -133,6 +137,11 @@ function Invoke-WordPreProcessItems
|
|||||||
Save-Setting "Documentation" "WordTitleProperty" $global:txtWordTitleProperty.Text
|
Save-Setting "Documentation" "WordTitleProperty" $global:txtWordTitleProperty.Text
|
||||||
Save-Setting "Documentation" "WordSubjectProperty" $global:txtWordSubjectProperty.Text
|
Save-Setting "Documentation" "WordSubjectProperty" $global:txtWordSubjectProperty.Text
|
||||||
|
|
||||||
|
Save-Setting "Documentation" "WordIncludeScripts" $global:chkWordIncludeScripts.IsChecked
|
||||||
|
Save-Setting "Documentation" "WordExcludeScriptSignature" $global:chkWordExcludeScriptSignature.IsChecked
|
||||||
|
Save-Setting "Documentation" "WordScriptTableStyle" $global:txtWordScriptTableStyle.Text
|
||||||
|
Save-Setting "Documentation" "WordScriptStyle" $global:txtWordScriptStyle.Text
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$script:wordApp = New-Object -ComObject Word.Application
|
$script:wordApp = New-Object -ComObject Word.Application
|
||||||
@@ -472,6 +481,8 @@ function Invoke-WordProcessItem
|
|||||||
Add-DocTableItems $obj $objectType $documentedObj.ApplicabilityRules $properties "SettingDetails.applicabilityRules"
|
Add-DocTableItems $obj $objectType $documentedObj.ApplicabilityRules $properties "SettingDetails.applicabilityRules"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Add-DocObjectSettings $obj $objectType $documentedObj
|
||||||
|
|
||||||
if(($documentedObj.Assignments | measure).Count -gt 0)
|
if(($documentedObj.Assignments | measure).Count -gt 0)
|
||||||
{
|
{
|
||||||
$params = @{}
|
$params = @{}
|
||||||
@@ -712,6 +723,49 @@ function Add-DocTableItems
|
|||||||
#$script:doc.Application.Selection.TypeParagraph()
|
#$script:doc.Application.Selection.TypeParagraph()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Add-DocTableScript
|
||||||
|
{
|
||||||
|
param($caption, $header, $script)
|
||||||
|
|
||||||
|
if(-not $script) { return }
|
||||||
|
|
||||||
|
$tblScriptStyle = (?? $global:txtWordScriptTableStyle.Text $global:txtWordTableStyle.Text)
|
||||||
|
|
||||||
|
$range = $script:doc.application.selection.range
|
||||||
|
|
||||||
|
$scriptTable = $script:doc.Tables.Add($range, 2, 1, [Microsoft.Office.Interop.Word.WdDefaultTableBehavior]::wdWord9TableBehavior, [Microsoft.Office.Interop.Word.WdAutoFitBehavior]::wdAutoFitWindow)
|
||||||
|
$scriptTable.ApplyStyleHeadingRows = $true
|
||||||
|
Set-DocObjectStyle $scriptTable $tblScriptStyle | Out-Null
|
||||||
|
|
||||||
|
if($header)
|
||||||
|
{
|
||||||
|
$scriptTable.Cell(1, 1).Range.Text = $header
|
||||||
|
}
|
||||||
|
|
||||||
|
$scriptTable.Cell(2,1).Range.Font.Bold = $false
|
||||||
|
$scriptTable.Cell(2, 1).Range.Text = $script
|
||||||
|
if($global:txtWordScriptStyle.Text)
|
||||||
|
{
|
||||||
|
Set-DocObjectStyle $scriptTable.Rows(2).Range $global:txtWordScriptStyle.Text | Out-Null
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$tmp = $script:wordStyles | Where Name -like "HTML Code"
|
||||||
|
if($tmp)
|
||||||
|
{
|
||||||
|
$scriptTable.Cell(2,1).Range.Font = $tmp.Style.Font
|
||||||
|
}
|
||||||
|
$scriptTable.Cell(2,1).Range.Font.Bold = $false
|
||||||
|
}
|
||||||
|
$scriptTable.Cell(2,1).Range.NoProofing = $true
|
||||||
|
|
||||||
|
# -2 = Table, 1 = Below
|
||||||
|
$scriptTable.Application.Selection.InsertCaption(-2, ". $caption", $null, 1)
|
||||||
|
|
||||||
|
# Add new row after the table
|
||||||
|
$script:doc.Application.Selection.TypeParagraph()
|
||||||
|
}
|
||||||
|
|
||||||
function Get-DocStyle
|
function Get-DocStyle
|
||||||
{
|
{
|
||||||
param($styleName)
|
param($styleName)
|
||||||
@@ -788,3 +842,86 @@ function Set-DocObjectStyle
|
|||||||
}
|
}
|
||||||
$styleSet
|
$styleSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function Add-DocObjectSettings
|
||||||
|
{
|
||||||
|
param($obj, $objectType, $documentedObj)
|
||||||
|
|
||||||
|
if($obj."@OData.Type" -eq "#microsoft.graph.deviceManagementScript")
|
||||||
|
{
|
||||||
|
if($obj.ScriptContent -and $global:chkWordIncludeScripts.IsChecked -eq $true)
|
||||||
|
{
|
||||||
|
$caption = "{1} - {0}" -f $obj.displayName,(Get-LanguageString "WindowsManagement.powerShellScriptObjectName")
|
||||||
|
Add-DocTableScript $caption $obj.FileName (Get-DocScriptContent $obj.ScriptContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($obj."@OData.Type" -eq "#microsoft.graph.deviceShellScript")
|
||||||
|
{
|
||||||
|
if($obj.ScriptContent -and $global:chkWordIncludeScripts.IsChecked -eq $true)
|
||||||
|
{
|
||||||
|
$caption = "{1} - {0}" -f $obj.displayName,(Get-LanguageString "WindowsManagement.shellScriptObjectName")
|
||||||
|
Add-DocTableScript $caption $obj.FileName (Get-DocScriptContent $obj.ScriptContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif($obj."@OData.Type" -eq "#microsoft.graph.deviceHealthScript")
|
||||||
|
{
|
||||||
|
if($obj.detectionScriptContent)
|
||||||
|
{
|
||||||
|
$caption = Get-LanguageString "ProactiveRemediations.Create.Settings.DetectionScriptMultiLineTextBox.label"
|
||||||
|
$header = "{1} - {0}" -f $obj.displayName,$caption
|
||||||
|
Add-DocTableScript $header $caption (Get-DocScriptContent $obj.detectionScriptContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
if($obj.remediationScriptContent)
|
||||||
|
{
|
||||||
|
$caption = Get-LanguageString "ProactiveRemediations.Create.Settings.RemediationScriptMultiLineTextBox.label"
|
||||||
|
$header = "{1} - {0}" -f $obj.displayName,$caption
|
||||||
|
Add-DocTableScript $header $caption (Get-DocScriptContent $obj.remediationScriptContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif($obj."@OData.Type" -eq "#microsoft.graph.win32LobApp")
|
||||||
|
{
|
||||||
|
foreach($rule in ($obj.requirementRules | Where { $_.'@OData.Type' -eq "#microsoft.graph.win32LobAppPowerShellScriptRequirement" } ))
|
||||||
|
{
|
||||||
|
$caption = "{0} - {1}" -f @($obj.displayName, "Requirement script")
|
||||||
|
|
||||||
|
Add-DocTableScript $caption $rule.displayName (Get-DocScriptContent $rule.scriptContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($rule in ($obj.detectionRules | Where { $_.'@OData.Type' -eq "#microsoft.graph.win32LobAppPowerShellScriptDetection" } ))
|
||||||
|
{
|
||||||
|
$caption = "{0} - {1}" -f @($obj.displayName,(Get-LanguageString "ProactiveRemediations.Create.Settings.DetectionScriptMultiLineTextBox.label"))
|
||||||
|
|
||||||
|
Add-DocTableScript $caption (Get-LanguageString "ProactiveRemediations.Create.Settings.DetectionScriptMultiLineTextBox.label") (Get-DocScriptContent $rule.scriptContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-DocScriptContent
|
||||||
|
{
|
||||||
|
param($encodeContent)
|
||||||
|
|
||||||
|
if(-not $encodeContent) { return }
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$scriptContent = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($encodeContent))
|
||||||
|
|
||||||
|
if($global:chkWordExcludeScriptSignature.IsChecked -eq $true)
|
||||||
|
{
|
||||||
|
$x = $scriptContent.IndexOf("# SIG # Begin signature block")
|
||||||
|
if($x -gt 0)
|
||||||
|
{
|
||||||
|
$scriptContent = $scriptContent.SubString(0,$x)
|
||||||
|
$scriptContent = $scriptContent + "# SIG # Begin signature block`nSignature data excluded..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$scriptContent
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ This module is for the Endpoint Manager/Intune View. It manages Export/Import/Co
|
|||||||
#>
|
#>
|
||||||
function Get-ModuleVersion
|
function Get-ModuleVersion
|
||||||
{
|
{
|
||||||
'3.1.12'
|
'3.1.13'
|
||||||
}
|
}
|
||||||
|
|
||||||
function Invoke-InitializeModule
|
function Invoke-InitializeModule
|
||||||
@@ -74,6 +74,7 @@ function Invoke-InitializeModule
|
|||||||
SubPath = "EndpointManager"
|
SubPath = "EndpointManager"
|
||||||
}) "EndpointManager"
|
}) "EndpointManager"
|
||||||
|
|
||||||
|
|
||||||
$viewPanel = Get-XamlObject ($global:AppRootFolder + "\Xaml\EndpointManagerPanel.xaml") -AddVariables
|
$viewPanel = Get-XamlObject ($global:AppRootFolder + "\Xaml\EndpointManagerPanel.xaml") -AddVariables
|
||||||
|
|
||||||
Set-EMViewPanel $viewPanel
|
Set-EMViewPanel $viewPanel
|
||||||
@@ -84,12 +85,13 @@ function Invoke-InitializeModule
|
|||||||
Description = "Manages Intune environments. This view can be used for copying objects in an Intune environment. It can also be used for backing up an entire Intune environment and cloning the Intune environment into another tenant."
|
Description = "Manages Intune environments. This view can be used for copying objects in an Intune environment. It can also be used for backing up an entire Intune environment and cloning the Intune environment into another tenant."
|
||||||
ID="IntuneGraphAPI"
|
ID="IntuneGraphAPI"
|
||||||
ViewPanel = $viewPanel
|
ViewPanel = $viewPanel
|
||||||
|
AuthenticationID = "MSAL"
|
||||||
ItemChanged = { Show-GraphObjects; Invoke-ModuleFunction "Invoke-GraphObjectsChanged"; Write-Status ""}
|
ItemChanged = { Show-GraphObjects; Invoke-ModuleFunction "Invoke-GraphObjectsChanged"; Write-Status ""}
|
||||||
Deactivating = { Invoke-EMDeactivateView }
|
Deactivating = { Invoke-EMDeactivateView }
|
||||||
Activating = { Invoke-EMActivatingView }
|
Activating = { Invoke-EMActivatingView }
|
||||||
Authentication = (Get-MSALAuthenticationObject)
|
Authentication = (Get-MSALAuthenticationObject)
|
||||||
Authenticate = { Invoke-EMAuthenticateToMSAL }
|
Authenticate = { Invoke-EMAuthenticateToMSAL }
|
||||||
AppInfo = (Get-GraphAppInfo "EMAzureApp" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547")
|
AppInfo = (Get-GraphAppInfo "EMAzureApp" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" "EM")
|
||||||
SaveSettings = { Invoke-EMSaveSettings }
|
SaveSettings = { Invoke-EMSaveSettings }
|
||||||
|
|
||||||
Permissions = @()
|
Permissions = @()
|
||||||
@@ -606,7 +608,7 @@ function Invoke-InitializeModule
|
|||||||
|
|
||||||
function Invoke-EMAuthenticateToMSAL
|
function Invoke-EMAuthenticateToMSAL
|
||||||
{
|
{
|
||||||
$global:EMViewObject.AppInfo = Get-GraphAppInfo "EMAzureApp" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547"
|
$global:EMViewObject.AppInfo = Get-GraphAppInfo "EMAzureApp" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" "EM"
|
||||||
Set-MSALCurrentApp $global:EMViewObject.AppInfo
|
Set-MSALCurrentApp $global:EMViewObject.AppInfo
|
||||||
& $global:msalAuthenticator.Login -Account (?? $global:MSALToken.Account.UserName (Get-Setting "" "LastLoggedOnUser"))
|
& $global:msalAuthenticator.Login -Account (?? $global:MSALToken.Account.UserName (Get-Setting "" "LastLoggedOnUser"))
|
||||||
}
|
}
|
||||||
@@ -622,7 +624,7 @@ function Invoke-EMActivatingView
|
|||||||
Show-MSALError
|
Show-MSALError
|
||||||
|
|
||||||
# Refresh values in case they have changed
|
# Refresh values in case they have changed
|
||||||
$global:EMViewObject.AppInfo = (Get-GraphAppInfo "EMAzureApp" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547")
|
$global:EMViewObject.AppInfo = (Get-GraphAppInfo "EMAzureApp" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" "EM")
|
||||||
if(-not $global:EMViewObject.Authentication)
|
if(-not $global:EMViewObject.Authentication)
|
||||||
{
|
{
|
||||||
$global:EMViewObject.Authentication = Get-MSALAuthenticationObject
|
$global:EMViewObject.Authentication = Get-MSALAuthenticationObject
|
||||||
@@ -647,6 +649,16 @@ function Invoke-EMSaveSettings
|
|||||||
Write-Status ""
|
Write-Status ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Set-EMUIStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-GraphAuthenticationUpdated
|
||||||
|
{
|
||||||
|
Set-EMUIStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-EMUIStatus
|
||||||
|
{
|
||||||
# Hide/Show Delete button
|
# Hide/Show Delete button
|
||||||
$allowDelete = Get-SettingValue "EMAllowDelete"
|
$allowDelete = Get-SettingValue "EMAllowDelete"
|
||||||
$global:btnDelete.Visibility = (?: ($allowDelete -eq $true) "Visible" "Collapsed")
|
$global:btnDelete.Visibility = (?: ($allowDelete -eq $true) "Visible" "Collapsed")
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ This module is for the Endpoint Info View. It shows read-only objects in Intune
|
|||||||
#>
|
#>
|
||||||
function Get-ModuleVersion
|
function Get-ModuleVersion
|
||||||
{
|
{
|
||||||
'3.1.3'
|
'3.1.4'
|
||||||
}
|
}
|
||||||
|
|
||||||
function Invoke-InitializeModule
|
function Invoke-InitializeModule
|
||||||
@@ -21,11 +21,12 @@ function Invoke-InitializeModule
|
|||||||
Description = "Displays read-only information in Intune."
|
Description = "Displays read-only information in Intune."
|
||||||
ID = "EMInfoGraphAPI"
|
ID = "EMInfoGraphAPI"
|
||||||
ViewPanel = $viewPanel
|
ViewPanel = $viewPanel
|
||||||
|
AuthenticationID = "MSAL"
|
||||||
ItemChanged = { Show-GraphObjects; Invoke-ModuleFunction "Invoke-GraphObjectsChanged"; Write-Status ""}
|
ItemChanged = { Show-GraphObjects; Invoke-ModuleFunction "Invoke-GraphObjectsChanged"; Write-Status ""}
|
||||||
Activating = { Invoke-EMInfoActivatingView }
|
Activating = { Invoke-EMInfoActivatingView }
|
||||||
Authentication = (Get-MSALAuthenticationObject)
|
Authentication = (Get-MSALAuthenticationObject)
|
||||||
Authenticate = { Invoke-EMInfoAuthenticateToMSAL }
|
Authenticate = { Invoke-EMInfoAuthenticateToMSAL }
|
||||||
AppInfo = (Get-GraphAppInfo "EM" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547")
|
AppInfo = (Get-GraphAppInfo "EMAzureApp" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" "EM")
|
||||||
SaveSettings = { Invoke-EMSaveSettings }
|
SaveSettings = { Invoke-EMSaveSettings }
|
||||||
Permissions = @()
|
Permissions = @()
|
||||||
})
|
})
|
||||||
@@ -95,7 +96,7 @@ function Invoke-EMInfoActivatingView
|
|||||||
|
|
||||||
function Invoke-EMInfoAuthenticateToMSAL
|
function Invoke-EMInfoAuthenticateToMSAL
|
||||||
{
|
{
|
||||||
$global:EMInfoViewObject.AppInfo = Get-GraphAppInfo "EMAzureApp" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547"
|
$global:EMInfoViewObject.AppInfo = Get-GraphAppInfo "EMAzureApp" "d1ddf0e4-d672-4dae-b554-9d5bdfd93547" "EM"
|
||||||
Set-MSALCurrentApp $global:EMInfoViewObject.AppInfo
|
Set-MSALCurrentApp $global:EMInfoViewObject.AppInfo
|
||||||
$usr = (?? $global:MSALToken.Account.UserName (Get-Setting "" "LastLoggedOnUser"))
|
$usr = (?? $global:MSALToken.Account.UserName (Get-Setting "" "LastLoggedOnUser"))
|
||||||
if($usr)
|
if($usr)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ $global:EMToolsViewObject = $null
|
|||||||
|
|
||||||
function Get-ModuleVersion
|
function Get-ModuleVersion
|
||||||
{
|
{
|
||||||
'1.0.1'
|
'1.0.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
function Invoke-InitializeModule
|
function Invoke-InitializeModule
|
||||||
@@ -76,6 +76,7 @@ function Add-EMToolsViewItem
|
|||||||
Title = "Intune Tools"
|
Title = "Intune Tools"
|
||||||
Description = "Additional tools for managing Intune"
|
Description = "Additional tools for managing Intune"
|
||||||
ID = "EMTools"
|
ID = "EMTools"
|
||||||
|
AuthenticationID = "MSAL"
|
||||||
ViewPanel = $viewPanel
|
ViewPanel = $viewPanel
|
||||||
ItemChanged = { Show-EMTool }
|
ItemChanged = { Show-EMTool }
|
||||||
Activating = { Invoke-EMToolsActivatingView }
|
Activating = { Invoke-EMToolsActivatingView }
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ This module manages Authentication for the application with MSAL. It is also res
|
|||||||
#>
|
#>
|
||||||
function Get-ModuleVersion
|
function Get-ModuleVersion
|
||||||
{
|
{
|
||||||
'3.3.0'
|
'3.3.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
$global:msalAuthenticator = $null
|
$global:msalAuthenticator = $null
|
||||||
@@ -37,6 +37,25 @@ function Invoke-InitializeModule
|
|||||||
Name = "Azure AD China"
|
Name = "Azure AD China"
|
||||||
Value = "china"
|
Value = "china"
|
||||||
URL = "login.partner.microsoftonline.cn"
|
URL = "login.partner.microsoftonline.cn"
|
||||||
|
GraphURL = "https://microsoftgraph.chinacloudapi.cn"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
$script:lstGCCEnvironments = @(
|
||||||
|
[PSCustomObject]@{
|
||||||
|
Name = "GCC"
|
||||||
|
Value = "gcc"
|
||||||
|
URL = "graph.microsoft.com"
|
||||||
|
},
|
||||||
|
[PSCustomObject]@{
|
||||||
|
Name = "GCC High"
|
||||||
|
Value = "gcgHigh"
|
||||||
|
URL = "graph.microsoft.us"
|
||||||
|
},
|
||||||
|
[PSCustomObject]@{
|
||||||
|
Name = "GCC DoD"
|
||||||
|
Value = "gccDoD"
|
||||||
|
URL = "dod-graph.microsoft.us"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -74,7 +93,7 @@ function Invoke-InitializeModule
|
|||||||
Title = "Use Default Permissions"
|
Title = "Use Default Permissions"
|
||||||
Key = "UseDefaultPermissions"
|
Key = "UseDefaultPermissions"
|
||||||
Type = "Boolean"
|
Type = "Boolean"
|
||||||
DefaultValue = $false
|
DefaultValue = $true
|
||||||
Description = "Default permissions of the selected app will be used when logging on. Some objects might not be accessable"
|
Description = "Default permissions of the selected app will be used when logging on. Some objects might not be accessable"
|
||||||
}) "MSAL"
|
}) "MSAL"
|
||||||
|
|
||||||
@@ -94,6 +113,14 @@ function Invoke-InitializeModule
|
|||||||
DefaultValue = "public"
|
DefaultValue = "public"
|
||||||
}) "MSAL"
|
}) "MSAL"
|
||||||
|
|
||||||
|
Add-SettingsObject (New-Object PSObject -Property @{
|
||||||
|
Title = "GCC Environment"
|
||||||
|
Key = "GCCEnvironment"
|
||||||
|
Type = "List"
|
||||||
|
ItemsSource = $script:lstGCCEnvironments
|
||||||
|
DefaultValue = "gcc"
|
||||||
|
}) "MSAL"
|
||||||
|
|
||||||
Add-MSALPrereq
|
Add-MSALPrereq
|
||||||
|
|
||||||
#$script:MSALDLLMissing = $true #!!!!
|
#$script:MSALDLLMissing = $true #!!!!
|
||||||
@@ -105,6 +132,7 @@ function Get-MSALAuthenticationObject
|
|||||||
{
|
{
|
||||||
$global:msalAuthenticator = New-Object PSObject -Property @{
|
$global:msalAuthenticator = New-Object PSObject -Property @{
|
||||||
Title = "MSAL"
|
Title = "MSAL"
|
||||||
|
ID = "MSAL"
|
||||||
SilentLogin = { Connect-MSALUser -Silent @args; }
|
SilentLogin = { Connect-MSALUser -Silent @args; }
|
||||||
Login = { Connect-MSALUser @args }
|
Login = { Connect-MSALUser @args }
|
||||||
Logout = { Disconnect-MSALUser }
|
Logout = { Disconnect-MSALUser }
|
||||||
@@ -130,6 +158,7 @@ function Initialize-MSALSettings
|
|||||||
function Clear-MSALCurentUserVaiables
|
function Clear-MSALCurentUserVaiables
|
||||||
{
|
{
|
||||||
$global:MSALTenantId = $null
|
$global:MSALTenantId = $null
|
||||||
|
$global:MSALGraphEnvironment = $null
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-MSALCurrentApp
|
function Get-MSALCurrentApp
|
||||||
@@ -144,6 +173,53 @@ function Set-MSALCurrentApp
|
|||||||
$global:appObj = $appInfoObj
|
$global:appObj = $appInfoObj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Set-MSALGraphEnvironment
|
||||||
|
{
|
||||||
|
param($user, $tenantId)
|
||||||
|
|
||||||
|
if($global:MSALGraphEnvironment)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$graphEnv = "graph.microsoft.com"
|
||||||
|
|
||||||
|
if($user)
|
||||||
|
{
|
||||||
|
$curAADEnv = $script:lstAADEnvironments | Where URL -eq $user.Environment
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$loginValue = Get-SettingValue "AzureLogin" "public" -TenantID (?? $tenantId $loginHint.user.TenantId)
|
||||||
|
$curAADEnv = $script:lstAADEnvironments | Where value -eq $loginValue
|
||||||
|
}
|
||||||
|
|
||||||
|
if($curAADEnv.Value -eq "usGov")
|
||||||
|
{
|
||||||
|
$gccEnv = Get-SettingValue "GCCEnvironment" "gcc" -TenantID (?? $tenantId $loginHint.user.TenantId)
|
||||||
|
if($gccEnv)
|
||||||
|
{
|
||||||
|
$GCCEnvObj = $script:lstGCCEnvironments | Where Value -eq $gccEnv
|
||||||
|
if($GCCEnvObj.URL)
|
||||||
|
{
|
||||||
|
$graphEnv = $GCCEnvObj.URL
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Write-Log "Could not find GCC environment based on $gccEnv. Default will be used" 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif($cuAADEnv.GraphURL)
|
||||||
|
{
|
||||||
|
$graphEnv = $cuAADEnv.GraphURL
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Log "Use Graph environment: $graphEnv"
|
||||||
|
$global:MSALGraphEnvironment = $graphEnv
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function Get-MSALUserInfo
|
function Get-MSALUserInfo
|
||||||
{
|
{
|
||||||
if($global:MSALToken)
|
if($global:MSALToken)
|
||||||
@@ -161,6 +237,11 @@ function Get-MSALUserInfo
|
|||||||
|
|
||||||
Write-Log "Get organization info"
|
Write-Log "Get organization info"
|
||||||
$global:Organization = (MSGraph\Invoke-GraphRequest -Url "Organization" -SkipAuthentication -ODataMetadata "Skip").Value
|
$global:Organization = (MSGraph\Invoke-GraphRequest -Url "Organization" -SkipAuthentication -ODataMetadata "Skip").Value
|
||||||
|
if($global:Organization)
|
||||||
|
{
|
||||||
|
if($global:Organization -is [array]) { $global:Organization = $global:Organization[0]}
|
||||||
|
Save-Setting $global:Organization.Id "_Name" $global:Organization.displayName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -642,34 +723,6 @@ function Connect-MSALUser
|
|||||||
$global:MSALToken = $null
|
$global:MSALToken = $null
|
||||||
}
|
}
|
||||||
|
|
||||||
if((Get-SettingValue "UseDefaultPermissions") -eq $true -or ($global:currentViewObject.ViewInfo.Permissions | measure).Count -eq 0)
|
|
||||||
{
|
|
||||||
[string[]] $Scopes = "https://graph.microsoft.com/.default"
|
|
||||||
$useDefaultPermissions = $true
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#$Scopes = [string[]]$global:PermissionScope
|
|
||||||
$reqScopes = [string[]]$global:msalAuthenticator.Permissions
|
|
||||||
$useDefaultPermissions = $false
|
|
||||||
|
|
||||||
$resolveRoles = ((Get-SettingValue "AzureADRoleRead" $false) -eq $true)
|
|
||||||
|
|
||||||
if($resolveRoles -and $global:msalAuthenticator.Permissions -notcontains "RoleManagement.Read.Directory")
|
|
||||||
{
|
|
||||||
# Adds the required permission for reading AAD directory roles
|
|
||||||
$reqScopes += "RoleManagement.Read.Directory"
|
|
||||||
}
|
|
||||||
|
|
||||||
$script:curViewPermissions = $global:currentViewObject.ViewInfo.Permissions
|
|
||||||
|
|
||||||
foreach($tmpScope in $script:curViewPermissions)
|
|
||||||
{
|
|
||||||
if($reqScopes -notcontains $tmpScope) { $reqScopes += $tmpScope }
|
|
||||||
}
|
|
||||||
$Scopes = [String[]]$reqScopes
|
|
||||||
}
|
|
||||||
|
|
||||||
$global:MSALApp = Get-MSALApp $global:appObj $Account
|
$global:MSALApp = Get-MSALApp $global:appObj $Account
|
||||||
$loginHint = ""
|
$loginHint = ""
|
||||||
|
|
||||||
@@ -682,10 +735,11 @@ function Connect-MSALUser
|
|||||||
{
|
{
|
||||||
# We're logging in with someone else...
|
# We're logging in with someone else...
|
||||||
Clear-MSALCurentUserVaiables
|
Clear-MSALCurentUserVaiables
|
||||||
|
$global:MSALToken = $null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# If we force interactive login the skip setting loginHint to force the user select account
|
# If we force interactive login then skip setting loginHint to force the user to select account
|
||||||
if(-not $loginHint -and $Interactive -ne $true)
|
if(-not $loginHint -and $Interactive -ne $true)
|
||||||
{
|
{
|
||||||
if($global:MSALAccounts)
|
if($global:MSALAccounts)
|
||||||
@@ -711,10 +765,47 @@ function Connect-MSALUser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($ForceRefresh -eq $true)
|
||||||
|
{
|
||||||
|
$global:MSALGraphEnvironment = $null
|
||||||
|
}
|
||||||
|
|
||||||
|
$tenantId = ?? $global:MSALTenantId $global:appObj.TenantId
|
||||||
|
|
||||||
|
Set-MSALGraphEnvironment $loginHint $tenantId
|
||||||
|
$useDefaultPermissions = (Get-SettingValue "UseDefaultPermissions" -TenantID (?? $tenantId $loginHint.HomeAccountId.TenantId))
|
||||||
|
|
||||||
|
if($useDefaultPermissions -eq $true -or ($global:currentViewObject.ViewInfo.Permissions | measure).Count -eq 0)
|
||||||
|
{
|
||||||
|
[string[]] $Scopes = "https://$($global:MSALGraphEnvironment)/.default"
|
||||||
|
$useDefaultPermissions = $true
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#$Scopes = [string[]]$global:PermissionScope
|
||||||
|
$reqScopes = [string[]]$global:msalAuthenticator.Permissions
|
||||||
|
$useDefaultPermissions = $false
|
||||||
|
|
||||||
|
$resolveRoles = ((Get-SettingValue "AzureADRoleRead" $false -TenantID (?? $tenantId $loginHint.HomeAccountId.TenantId)) -eq $true)
|
||||||
|
|
||||||
|
if($resolveRoles -and $global:msalAuthenticator.Permissions -notcontains "RoleManagement.Read.Directory")
|
||||||
|
{
|
||||||
|
# Adds the required permission for reading AAD directory roles
|
||||||
|
$reqScopes += "RoleManagement.Read.Directory"
|
||||||
|
}
|
||||||
|
|
||||||
|
$script:curViewPermissions = $global:currentViewObject.ViewInfo.Permissions
|
||||||
|
|
||||||
|
foreach($tmpScope in $script:curViewPermissions)
|
||||||
|
{
|
||||||
|
if($reqScopes -notcontains $tmpScope) { $reqScopes += $tmpScope }
|
||||||
|
}
|
||||||
|
$Scopes = [String[]]$reqScopes
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$prompConsent = $false
|
$prompConsent = $false
|
||||||
$authResult = $null
|
$authResult = $null
|
||||||
$tenantId = ?? $global:MSALTenantId $global:appObj.TenantId
|
|
||||||
#$authority = ?? $global:MSALApp.Authority $global:appObj.Authority
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -851,7 +942,7 @@ function Connect-MSALUser
|
|||||||
if($currentLoggedInUserId -ne $authResult.Account.HomeAccountId.Identifier)
|
if($currentLoggedInUserId -ne $authResult.Account.HomeAccountId.Identifier)
|
||||||
{
|
{
|
||||||
$script:AccessableTenants = $null
|
$script:AccessableTenants = $null
|
||||||
if($authResult -and (Get-Setting "" "GetTenantList" $false) -eq $true)
|
if($authResult -and (Get-SettingValue "GetTenantList" -TenantID $authResult.Account.HomeAccountId.TenantId) -eq $true)
|
||||||
{
|
{
|
||||||
#########################################################################################################
|
#########################################################################################################
|
||||||
### Get tenant list
|
### Get tenant list
|
||||||
@@ -916,10 +1007,79 @@ function Connect-MSALUser
|
|||||||
|
|
||||||
Write-LogDebug "User, tenant or app has changed"
|
Write-LogDebug "User, tenant or app has changed"
|
||||||
Get-MSALUserInfo
|
Get-MSALUserInfo
|
||||||
|
Invoke-MSALCheckObjectViewAccess
|
||||||
Invoke-ModuleFunction "Invoke-GraphAuthenticationUpdated"
|
Invoke-ModuleFunction "Invoke-GraphAuthenticationUpdated"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Invoke-MSALCheckObjectViewAccess
|
||||||
|
{
|
||||||
|
foreach($viewObjInfo in ($global:viewObjects | Where { $_.ViewInfo.AuthenticationID -eq "MSAL" }))
|
||||||
|
{
|
||||||
|
$viewObjInfo = $global:viewObjects | Where { $_.ViewInfo.Id -eq $global:EMViewObject.Id }
|
||||||
|
|
||||||
|
if($viewObjInfo)
|
||||||
|
{
|
||||||
|
$accessToken = Get-JWTtoken $global:MSALToken.AccessToken
|
||||||
|
if($accessToken.Payload.scp)
|
||||||
|
{
|
||||||
|
$curPermissions = $accessToken.Payload.scp.Split(" ")
|
||||||
|
foreach($viewItem in $viewObjInfo.ViewItems)
|
||||||
|
{
|
||||||
|
$full = 0
|
||||||
|
$partial = 0
|
||||||
|
|
||||||
|
foreach($permission in $viewItem.Permissons)
|
||||||
|
{
|
||||||
|
if($curPermissions -contains $permission)
|
||||||
|
{
|
||||||
|
$full++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
# Check read access
|
||||||
|
$arrTemp = $permission.Split('.')
|
||||||
|
if($arrTemp[1] -eq "ReadWrite")
|
||||||
|
{
|
||||||
|
$arrTemp[1] = "Read"
|
||||||
|
$arrTemp -join "."
|
||||||
|
}
|
||||||
|
if($curPermissions -contains $permission)
|
||||||
|
{
|
||||||
|
$partial++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$hasAccess = $false
|
||||||
|
if($viewItem.Permissons.Count -eq $full)
|
||||||
|
{
|
||||||
|
$accessType = "Full"
|
||||||
|
$hasAccess = $true
|
||||||
|
}
|
||||||
|
elseif($partial -gt 0)
|
||||||
|
{
|
||||||
|
$accessType = "Limited"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$accessType = "None"
|
||||||
|
}
|
||||||
|
|
||||||
|
if(-not ($viewItem.PSObject.Properties | Where Name -eq "@HasPermissions"))
|
||||||
|
{
|
||||||
|
$viewItem | Add-Member -NotePropertyName "@HasPermissions" -NotePropertyValue $hasAccess
|
||||||
|
$viewItem | Add-Member -NotePropertyName "@AccessType" -NotePropertyValue $accessType
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$viewItem."@HasPermissions" = $hasAccess
|
||||||
|
$viewItem."@AccessType" = $accessType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Show-ViewMenu
|
||||||
|
}
|
||||||
|
|
||||||
function Disconnect-MSALUser
|
function Disconnect-MSALUser
|
||||||
{
|
{
|
||||||
param($user, [switch]$force, [switch]$PassThru)
|
param($user, [switch]$force, [switch]$PassThru)
|
||||||
@@ -1039,7 +1199,9 @@ function Get-MSALProfileEllipse
|
|||||||
$icon.Margin = "0,0,5,0"
|
$icon.Margin = "0,0,5,0"
|
||||||
$grdAccount.Children.Add($icon) | Out-Null
|
$grdAccount.Children.Add($icon) | Out-Null
|
||||||
|
|
||||||
$lbObj = [Windows.Markup.XamlReader]::Parse("<TextBlock $wpfNS>$($account.UserName)<LineBreak/>$($account.HomeAccountId.TenantId)</TextBlock>")
|
$tenantName = Get-Setting $account.HomeAccountId.TenantId "_Name" $account.HomeAccountId.TenantId
|
||||||
|
|
||||||
|
$lbObj = [Windows.Markup.XamlReader]::Parse("<TextBlock $wpfNS>$($account.UserName)<LineBreak/>$($tenantName)</TextBlock>")
|
||||||
$lbObj.SetValue([System.Windows.Controls.Grid]::ColumnProperty,1)
|
$lbObj.SetValue([System.Windows.Controls.Grid]::ColumnProperty,1)
|
||||||
$grdAccount.Children.Add($lbObj) | Out-Null
|
$grdAccount.Children.Add($lbObj) | Out-Null
|
||||||
|
|
||||||
@@ -1262,7 +1424,9 @@ function Get-MSALProfileEllipse
|
|||||||
$icon.Margin = "0,0,5,0"
|
$icon.Margin = "0,0,5,0"
|
||||||
$grdLogin.Children.Add($icon) | Out-Null
|
$grdLogin.Children.Add($icon) | Out-Null
|
||||||
|
|
||||||
$lbObj = [Windows.Markup.XamlReader]::Parse("<TextBlock $wpfNS>$($account.UserName)<LineBreak/>$($account.HomeAccountId.TenantId)</TextBlock>")
|
$tenantName = Get-Setting $account.HomeAccountId.TenantId "_Name" $account.HomeAccountId.TenantId
|
||||||
|
|
||||||
|
$lbObj = [Windows.Markup.XamlReader]::Parse("<TextBlock $wpfNS>$($account.UserName)<LineBreak/>$($tenantName)</TextBlock>")
|
||||||
$lbObj.SetValue([System.Windows.Controls.Grid]::ColumnProperty,1)
|
$lbObj.SetValue([System.Windows.Controls.Grid]::ColumnProperty,1)
|
||||||
$grdLogin.Children.Add($lbObj) | Out-Null
|
$grdLogin.Children.Add($lbObj) | Out-Null
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,10 @@ This module manages Microsoft Grap fuctions like calling APIs, managing graph ob
|
|||||||
#>
|
#>
|
||||||
function Get-ModuleVersion
|
function Get-ModuleVersion
|
||||||
{
|
{
|
||||||
'3.1.8'
|
'3.1.9'
|
||||||
}
|
}
|
||||||
|
|
||||||
$global:MSGraphGlobalApps = @(
|
$global:MSGraphGlobalApps = @(
|
||||||
#Authority="https://login.microsoftonline.com/organizations/"
|
|
||||||
(New-Object PSObject -Property @{Name="";ClientId="";RedirectUri="";Authority=""}),
|
(New-Object PSObject -Property @{Name="";ClientId="";RedirectUri="";Authority=""}),
|
||||||
(New-Object PSObject -Property @{Name="Microsoft Intune PowerShell";ClientId="d1ddf0e4-d672-4dae-b554-9d5bdfd93547";RedirectUri="urn:ietf:wg:oauth:2.0:oob"; }),
|
(New-Object PSObject -Property @{Name="Microsoft Intune PowerShell";ClientId="d1ddf0e4-d672-4dae-b554-9d5bdfd93547";RedirectUri="urn:ietf:wg:oauth:2.0:oob"; }),
|
||||||
(New-Object PSObject -Property @{Name="Microsoft Graph PowerShell";ClientId="14d82eec-204b-4c2f-b7e8-296a70dab67e";RedirectUri="https://login.microsoftonline.com/common/oauth2/nativeclient";})
|
(New-Object PSObject -Property @{Name="Microsoft Graph PowerShell";ClientId="14d82eec-204b-4c2f-b7e8-296a70dab67e";RedirectUri="https://login.microsoftonline.com/common/oauth2/nativeclient";})
|
||||||
@@ -164,7 +163,7 @@ function Invoke-InitializeModule
|
|||||||
|
|
||||||
function Get-GraphAppInfo
|
function Get-GraphAppInfo
|
||||||
{
|
{
|
||||||
param($settingId, $defaultAppId)
|
param($settingId, $defaultAppId, $prefix)
|
||||||
|
|
||||||
$graphAppId = Get-SettingValue $settingId
|
$graphAppId = Get-SettingValue $settingId
|
||||||
|
|
||||||
@@ -235,6 +234,9 @@ function Invoke-GraphRequest
|
|||||||
|
|
||||||
$ODataMetadata = "full", # full, minimal, none or skip
|
$ODataMetadata = "full", # full, minimal, none or skip
|
||||||
|
|
||||||
|
[ValidateSet("BETA","v1.0")]
|
||||||
|
$GraphVersion = "BETA",
|
||||||
|
|
||||||
[switch]
|
[switch]
|
||||||
$AllPages,
|
$AllPages,
|
||||||
|
|
||||||
@@ -307,7 +309,7 @@ function Invoke-GraphRequest
|
|||||||
|
|
||||||
if(($Url -notmatch "^http://|^https://"))
|
if(($Url -notmatch "^http://|^https://"))
|
||||||
{
|
{
|
||||||
$Url = $global:graphURL + "/" + $Url.TrimStart('/')
|
$Url = "https://$((?? $global:MSALGraphEnvironment "graph.microsoft.com"))/$GraphVersion/" + $Url.TrimStart('/')
|
||||||
$Url = $Url -replace "%OrganizationId%", $global:Organization.Id
|
$Url = $Url -replace "%OrganizationId%", $global:Organization.Id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,6 +471,14 @@ function Show-GraphObjects
|
|||||||
|
|
||||||
if(-not $global:MSALToken)
|
if(-not $global:MSALToken)
|
||||||
{
|
{
|
||||||
|
$global:txtNotLoggedIn.Content = "Not logged in. Please login to view objects"
|
||||||
|
$global:grdNotLoggedIn.Visibility = "Visible"
|
||||||
|
$global:grdData.Visibility = "Collapsed"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
elseif($global:curObjectType.'@AccessType' -eq "None")
|
||||||
|
{
|
||||||
|
$global:txtNotLoggedIn.Content = "You don't have the required permissons to access $($global:curObjectType.Title).`n`nRequired perimssons: $($global:curObjectType.Permissons)"
|
||||||
$global:grdNotLoggedIn.Visibility = "Visible"
|
$global:grdNotLoggedIn.Visibility = "Visible"
|
||||||
$global:grdData.Visibility = "Collapsed"
|
$global:grdData.Visibility = "Collapsed"
|
||||||
return
|
return
|
||||||
@@ -540,6 +550,7 @@ function Show-GraphObjects
|
|||||||
$column.Binding = $binding
|
$column.Binding = $binding
|
||||||
|
|
||||||
$tableColumns += $prop.Name
|
$tableColumns += $prop.Name
|
||||||
|
|
||||||
$dgObjects.Columns.Add($column)
|
$dgObjects.Columns.Add($column)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -577,7 +588,12 @@ function Show-GraphObjects
|
|||||||
# Show/Hide buttons based on object type
|
# Show/Hide buttons based on object type
|
||||||
foreach($ctrl in $spSubMenu.Children)
|
foreach($ctrl in $spSubMenu.Children)
|
||||||
{
|
{
|
||||||
if(-not $global:curObjectType.ShowButtons -or ($global:curObjectType.ShowButtons | Where-Object { $ctrl.Name -like "*$($_)" } ))
|
if($ctrl.Name -eq "btnDelete")
|
||||||
|
{
|
||||||
|
$allowDelete = Get-SettingValue "EMAllowDelete"
|
||||||
|
$ctrl.Visibility = (?: ($allowDelete -eq $true) "Visible" "Collapsed")
|
||||||
|
}
|
||||||
|
elseif(-not $global:curObjectType.ShowButtons -or ($global:curObjectType.ShowButtons | Where-Object { $ctrl.Name -like "*$($_)" } ))
|
||||||
{
|
{
|
||||||
Write-LogDebug "Show $($ctrl.Name)"
|
Write-LogDebug "Show $($ctrl.Name)"
|
||||||
$ctrl.Visibility = "Visible"
|
$ctrl.Visibility = "Visible"
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -1,12 +1,20 @@
|
|||||||
# IntuneManagement with PowerShell and WPF UI
|
# IntuneManagement with PowerShell and WPF UI
|
||||||
|
|
||||||
These PowerShell scripts are using Microsoft Authentication Library (MSAL), Microsoft Graph APIs and Azure Management APIs to manage objects in Intune and Azure. The scripts has a simple WPF UI and it supports operations like Export, Import, Copy and Download.
|
<p align="center">
|
||||||
|
<a href="https://twitter.com/Micke_K_72">
|
||||||
|
<img src="https://img.shields.io/twitter/follow/Micke_K_72.svg?style=social" target="_blank" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
These PowerShell scripts are using Microsoft Authentication Library (MSAL), Microsoft Graph APIs and Azure Management APIs to manage objects in Intune and Azure. The scripts has a simple WPF UI and it supports operations like Export, Import, Copy, Download, Compare etc.
|
||||||
|
|
||||||
This makes it easy to backup or clone a complete Intune environment. The scripts can export and import objects including assignments and support import/export between tenants. The scripts will create a migration table during export and use that for importing assignments in other environments. It will create missing groups in the target environment during import. Group information like name, description and type will be imported based on the exported group e.g. dynamic groups are supported. There will be one json file for each group in the export folder.
|
This makes it easy to backup or clone a complete Intune environment. The scripts can export and import objects including assignments and support import/export between tenants. The scripts will create a migration table during export and use that for importing assignments in other environments. It will create missing groups in the target environment during import. Group information like name, description and type will be imported based on the exported group e.g. dynamic groups are supported. There will be one json file for each group in the export folder.
|
||||||
|
|
||||||
The script also support dependencies e.g. an App Protection is depending on an App, Policy Sets are depending on Compliance Policies, objects has Scope Tags etc. Dependency support requires exported json files and that the dependency objects are imported in the environment. The script uses the exported json files to get the Id and name's of the exported object and uses that information and updates Id's before import an object from a json file. The Bulk Import form shows the import order of the objects. The objects with the lowest order number will be imported first.
|
The script also support dependencies e.g. an App Protection is depending on an App, Policy Sets are depending on Compliance Policies, objects has Scope Tags etc. Dependency support requires exported json files and that the dependency objects are imported in the environment. The script uses the exported json files to get the Id and name's of the exported object and uses that information and updates Id's before import an object from a json file. The Bulk Import form shows the import order of the objects. The objects with the lowest order number will be imported first.
|
||||||
|
|
||||||

|
<p align="center">
|
||||||
|
<img src="https://raw.githubusercontent.com/Micke-K/IntuneManagement/master/IntuneManagement.PNG" height="80%" width="80%"/>
|
||||||
|
</p>
|
||||||
|
|
||||||
This PowerShell application is based on the foundation modules CloudAPIPowerShellManagement and Core. These modules manages UI, settings, logging etc. The functionality for the application is located in the extension modules. This makes it easy to add/remove features, views etc. Additional features will be added...
|
This PowerShell application is based on the foundation modules CloudAPIPowerShellManagement and Core. These modules manages UI, settings, logging etc. The functionality for the application is located in the extension modules. This makes it easy to add/remove features, views etc. Additional features will be added...
|
||||||
|
|
||||||
@@ -79,13 +87,17 @@ The documentation method is a bit slower but will show the values as they are st
|
|||||||
|
|
||||||
Bulk compare is supported. This can be performed in two ways:
|
Bulk compare is supported. This can be performed in two ways:
|
||||||
|
|
||||||
* **Export File** - This will read each exported file and compare it with the existing object
|
* **Intune Objects with Exported Files** - This will read each exported file and compare it with the existing object
|
||||||
|
|
||||||
The result file will be stored in the exported folder structure. Either in the Object Type folder or the parent folder depending on the Save as setting.
|
The result file will be stored in the exported folder structure. Either in the Object Type folder or the parent folder depending on the Save as setting.
|
||||||
|
|
||||||
**Note:** This cannot be used with files exported from a different environment since it used the Id as identifier
|
**Note:** This cannot be used with files exported from a different environment since it used the Id as identifier
|
||||||
|
|
||||||
* **Named Objects** - Compare file based on patterns
|
* **Named Objects in Intune** - Compare Intune objects based on patterns
|
||||||
|
|
||||||
|
This can be used in where a pattern is used separate objects between different environments e.g. [Test] Policy 1 vs [Prod] Policy 1.
|
||||||
|
|
||||||
|
* **Files in Exported Folders** - Compare two exported folders
|
||||||
|
|
||||||
This can be used in where a pattern is used separate objects between different environments e.g. [Test] Policy 1 vs [Prod] Policy 1.
|
This can be used in where a pattern is used separate objects between different environments e.g. [Test] Policy 1 vs [Prod] Policy 1.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,45 @@
|
|||||||
# Release Notes
|
# Release Notes
|
||||||
|
|
||||||
|
## 3.3.1 (Beta) - 2021-10-28
|
||||||
|
|
||||||
|
This is a **BETA** release. It contains core changes for Authentication and Settings management. Please report any issues [here](https://github.com/Micke-K/IntuneManagement/issues).
|
||||||
|
|
||||||
|
**New features**
|
||||||
|
|
||||||
|
- Added support for selecting GCC when using US Government Cloud
|
||||||
|
|
||||||
|
- Tenant Specific Setting
|
||||||
|
|
||||||
|
The script now supports tenant specific settings. This can be used in scenarios like: only allow delete on you test environments, tenant specific Intune app folders etc.
|
||||||
|
Login settings like Cloud and GCC is only used if logging on with a cached token. It will otherwise use the current tenant settings.
|
||||||
|
|
||||||
|
**Test feedback request:** If there are any users accessing multiple cloud environments like US Government with different GCC levels, please report any issues, working or not. Please report it to [Issue 26](https://github.com/Micke-K/IntuneManagement/issues/26)
|
||||||
|
|
||||||
|
Note: Not all settings have be tested and verified and only Setting Values are supported e.g. last Bulk Compare strings are global. Cached settings might not be updated when connecting to another tenant.
|
||||||
|
|
||||||
|
- Log View
|
||||||
|
|
||||||
|
View the log of the current session in the app
|
||||||
|
|
||||||
|
- Added support for documenting scripts for Word
|
||||||
|
This is based on [Issue 34](https://github.com/Micke-K/IntuneManagement/issues/34)
|
||||||
|
|
||||||
|
- New Script options in the Output option tab e.g. enable/disable script documentation, remove PowerShell signature block and documentation styles
|
||||||
|
- Supports PowerShell/Shell scripts, Proactive Remediations and Win32 Apps (Requirement/Detection scripts)
|
||||||
|
- Scripts will be documented in a separate table with style *HTLM Code* by default. Spell check is disabled for the script text.
|
||||||
|
|
||||||
|
- Permission detection if **Use Default Permissions** is enabled
|
||||||
|
|
||||||
|
Default permissions will only use the permission consented to the selected Azure App. The script will check the required permissions with the Access Token. If permissions are missing for one or more objects, they will be marked as red in the menu or they can be excluded from the menu by enable **Hide No-access items** in Settings
|
||||||
|
|
||||||
|
**Default Settings Value Changes**
|
||||||
|
|
||||||
|
* **Use Default Permissions** is now set to Disabled by default. With the Tenant Specific Settings feature, this can now be enabled globally or per tenant. Consultants accessing multiple environments might not have permissions to grant consent requests so this could be enabled on a global level and then disabled for tenants where the permissions can be added.
|
||||||
|
|
||||||
|
**Fixes**
|
||||||
|
|
||||||
|
* Fixed an issue when using Json settings where it could not add child settings
|
||||||
|
|
||||||
## 3.3.0 (Beta) - 2021-10-17
|
## 3.3.0 (Beta) - 2021-10-17
|
||||||
|
|
||||||
This is a **BETA** release. It contains core changes for Authentication and Settings management. Please report any issues [here](https://github.com/Micke-K/IntuneManagement/issues).
|
This is a **BETA** release. It contains core changes for Authentication and Settings management. Please report any issues [here](https://github.com/Micke-K/IntuneManagement/issues).
|
||||||
|
|||||||
@@ -18,6 +18,11 @@
|
|||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@@ -150,4 +155,28 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
<CheckBox Grid.Column='1' Grid.Row='17' Name='chkWordOpenDocument' VerticalAlignment="Center" IsChecked="true" />
|
<CheckBox Grid.Column='1' Grid.Row='17' Name='chkWordOpenDocument' VerticalAlignment="Center" IsChecked="true" />
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" Grid.Row='18' Margin="0,0,5,0">
|
||||||
|
<Label Content="Document scripts" />
|
||||||
|
<Rectangle Style="{DynamicResource InfoIcon}" ToolTip="Include scripts in the documentation" />
|
||||||
|
</StackPanel>
|
||||||
|
<CheckBox Grid.Column='1' Grid.Row='18' Name='chkWordIncludeScripts' VerticalAlignment="Center" IsChecked="true" />
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" Grid.Row='19' Margin="0,0,5,0">
|
||||||
|
<Label Content="Remove script signature" />
|
||||||
|
<Rectangle Style="{DynamicResource InfoIcon}" ToolTip="Remove signature block from PowerShell scripts to reduce script documentation size" />
|
||||||
|
</StackPanel>
|
||||||
|
<CheckBox Grid.Column='1' Grid.Row='19' Name='chkWordExcludeScriptSignature' VerticalAlignment="Center" IsChecked="true" />
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="0,5,5,0" Grid.Row="21">
|
||||||
|
<Label Content="Script table style" />
|
||||||
|
<Rectangle Style="{DynamicResource InfoIcon}" ToolTip="Specify the table style to use for scripts. Ducument table style will be use as default" />
|
||||||
|
</StackPanel>
|
||||||
|
<TextBox Grid.Column='1' Grid.Row='21' Name='txtWordScriptTableStyle' Margin="0,5,5,5"/>
|
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="0,5,5,0" Grid.Row="22">
|
||||||
|
<Label Content="Script font style" />
|
||||||
|
<Rectangle Style="{DynamicResource InfoIcon}" ToolTip="Specify the font style to use for documenting scripts. HTML Code is used as default" />
|
||||||
|
</StackPanel>
|
||||||
|
<TextBox Grid.Column='1' Grid.Row='22' Name='txtWordScriptStyle' Margin="0,5,5,5"/>
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
59
Xaml/LogInfo.xaml
Normal file
59
Xaml/LogInfo.xaml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5,5,5,5">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="4*" MinHeight="300" />
|
||||||
|
<RowDefinition Height="3" />
|
||||||
|
<RowDefinition Height="1*" MinHeight="100" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<DataGrid Name="dgLogInfo"
|
||||||
|
AutoGenerateColumns="False"
|
||||||
|
SelectionMode="Single"
|
||||||
|
SelectionUnit="FullRow"
|
||||||
|
CanUserAddRows="False">
|
||||||
|
<DataGrid.RowStyle>
|
||||||
|
<Style TargetType="DataGridRow">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding Type}" Value="3">
|
||||||
|
<Setter Property="Foreground" Value="Red"></Setter>
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding Type}" Value="2">
|
||||||
|
<Setter Property="Foreground" Value="Orange"></Setter>
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</DataGrid.RowStyle>
|
||||||
|
<DataGrid.Columns>
|
||||||
|
<DataGridTextColumn Header="Date" Binding="{Binding DateTime, StringFormat={}{0:d}}" IsReadOnly="True" Width="Auto" />
|
||||||
|
<DataGridTextColumn Header="Time" Binding="{Binding DateTime, StringFormat={}{0:HH:mm.ss.fff}}" IsReadOnly="True" Width="Auto" />
|
||||||
|
<DataGridTextColumn Header="Type" Binding="{Binding TypeText}" IsReadOnly="True" Width="Auto" />
|
||||||
|
<DataGridTemplateColumn Header="Text">
|
||||||
|
<DataGridTemplateColumn.CellTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock Text="{Binding Path=Text}" TextWrapping="NoWrap" />
|
||||||
|
</DataTemplate>
|
||||||
|
</DataGridTemplateColumn.CellTemplate>
|
||||||
|
</DataGridTemplateColumn>
|
||||||
|
</DataGrid.Columns>
|
||||||
|
</DataGrid>
|
||||||
|
|
||||||
|
<GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
|
||||||
|
|
||||||
|
<Grid Grid.Row="3">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="5" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<TextBlock Text="Date\Time" Grid.Row="0" Grid.Column="0" />
|
||||||
|
<TextBlock Text="{Binding Path=DateTime, StringFormat={}{0:yyyy-MM-dd HH:mm.ss.fff}}" Grid.Row="0" Grid.Column="2" />
|
||||||
|
|
||||||
|
<TextBox Grid.Row="1" Grid.ColumnSpan="99" Text="{Binding Path=Text}" HorizontalAlignment="Stretch" Name="txtLogInfo" IsReadOnly="True" AcceptsReturn="true" />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
@@ -34,8 +34,11 @@
|
|||||||
<Menu Name="mnuMain" Padding="0,5,0,5" Grid.ColumnSpan="2" >
|
<Menu Name="mnuMain" Padding="0,5,0,5" Grid.ColumnSpan="2" >
|
||||||
<MenuItem Header="_File" >
|
<MenuItem Header="_File" >
|
||||||
<MenuItem Header="_Settings" Name="mnuSettings" />
|
<MenuItem Header="_Settings" Name="mnuSettings" />
|
||||||
|
<MenuItem Header="_Tenant Settings" Name="mnuTenantSettings" />
|
||||||
|
<Separator />
|
||||||
<MenuItem Header="_Release Notes" Name="mnuUpdates" />
|
<MenuItem Header="_Release Notes" Name="mnuUpdates" />
|
||||||
<MenuItem Header="_About" Name="mnuAbout" />
|
<MenuItem Header="_About" Name="mnuAbout" />
|
||||||
|
<Separator />
|
||||||
<MenuItem Header="_Exit" Name="mnuExit" />
|
<MenuItem Header="_Exit" Name="mnuExit" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Name="mnuViews" Header="_Views" >
|
<MenuItem Name="mnuViews" Header="_Views" >
|
||||||
@@ -45,7 +48,7 @@
|
|||||||
|
|
||||||
<Grid Name="grdViewPanel" Grid.Column="1" Grid.RowSpan="2" Grid.Row="1" Margin="0,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
|
<Grid Name="grdViewPanel" Grid.Column="1" Grid.RowSpan="2" Grid.Row="1" Margin="0,5,5,5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
|
||||||
|
|
||||||
<Grid Grid.Row="1" Margin="5" VerticalAlignment="Stretch">
|
<Grid Grid.Row="1" Margin="5" VerticalAlignment="Stretch" Name="grdViewItemMenu">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
@@ -64,6 +67,18 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListBox.ItemTemplate>
|
</ListBox.ItemTemplate>
|
||||||
|
<ListBox.Resources>
|
||||||
|
<Style TargetType="ListBoxItem">
|
||||||
|
<Style.Triggers>
|
||||||
|
<DataTrigger Binding="{Binding @AccessType}" Value="None">
|
||||||
|
<Setter Property="Foreground" Value="Red" />
|
||||||
|
</DataTrigger>
|
||||||
|
<DataTrigger Binding="{Binding @AccessType}" Value="Limited">
|
||||||
|
<Setter Property="Foreground" Value="Orange" />
|
||||||
|
</DataTrigger>
|
||||||
|
</Style.Triggers>
|
||||||
|
</Style>
|
||||||
|
</ListBox.Resources>
|
||||||
</ListBox>
|
</ListBox>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,19 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Grid Grid.ColumnSpan="2">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<TextBlock Margin="5" Name="txtOrganization" FontWeight="Bold" />
|
<TextBlock Margin="5" Name="txtOrganization" FontWeight="Bold" />
|
||||||
<Button Margin="5" Name="lnkLogout" Content="Sign out" Grid.Column="2" Style="{DynamicResource LinkButton}" HorizontalAlignment="Right"/>
|
<Button Margin="5" Name="lnkLogout" Content="Sign out" Grid.Column="2" Style="{DynamicResource LinkButton}" HorizontalAlignment="Right"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<TextBlock Margin="5" Name="txtUsername" Grid.Row="1" Grid.Column="2" FontWeight="Bold" FontSize="24" />
|
<TextBlock Margin="5" Name="txtUsername" Grid.Row="1" Grid.Column="2" FontWeight="Bold" FontSize="24" />
|
||||||
<TextBlock Margin="5" Name="txtLogonName" Grid.Row="2" Grid.Column="2" />
|
<TextBlock Margin="5" Name="txtLogonName" Grid.Row="2" Grid.Column="2" />
|
||||||
|
|
||||||
|
|||||||
@@ -6,18 +6,12 @@
|
|||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<!--
|
|
||||||
<StackPanel Name="spSettings" Grid.Column="1"
|
|
||||||
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
|
||||||
Grid.IsSharedSizeScope='True' Margin="0">
|
|
||||||
|
|
||||||
</StackPanel>
|
|
||||||
-->
|
|
||||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Padding="0,0,5,0">
|
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Padding="0,0,5,0">
|
||||||
<Grid Name="spSettings" Grid.Column="1"
|
<Grid Name="spSettings" Grid.Column="1"
|
||||||
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||||
Grid.IsSharedSizeScope='True' Margin="0">
|
Grid.IsSharedSizeScope='True' Margin="0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|||||||
Reference in New Issue
Block a user