Automating App Deployment with Winget and Intune

Update 28/06/23 – Version 4.0 now lets you use a command line parameter to specify install and uninstall group names

There are some incredible community tools out there for app deployment via Winget and Intune, but as I’m sure you’ve noticed, I prefer a more hands-off script so decided to make my own.

I also stumbled across these PowerShell tools from a previous Microsoft Hackathon which opened up a world of possibilities!

As always, my script can be found on Github here or on PowerShell Gallery:

Install-Script -Name deploy-winget-win32-multiple

When launching the script you will be presented with a credentials box which will authenticate against both Azure AD and Microsoft Graph (you may get a second password prompt for AzureAD).

At this point it will also download the latest copy of the intunewin utility and install Winget if it’s not already installed (you’ll need this for the app list)

Once authenticated, the script will sit there for a minute while it grabs all of the apps available on Winget and then bring a GridView from PowerShell with a list of everything available:

As it uses the native GridView, you can do advanced filtering and select multiple apps via Ctrl or Shift select.

When you click ok, the magic happens!

The script churns away to create:

  • Directory in C:\Temp to store files
  • AzureAD Install and Uninstall Groups
  • Install and Uninstall PowerShell scripts
  • Custom Detection Script
  • Proactive Remediation (to update the app daily)
  • The intunewin file itself

Once created it will:

  • Upload the Intunewin file to Intune
  • Assign Install and Uninstall groups to it
  • Assign the Proactive Remediation to the install group

It’s all at the command line so fully silent, once you’ve selected your apps, leave it running, sit back and have a drink. All scripts use the exact app ID so no worries of it grabbing the wrong one either.

It’s all fully logged in the Windows Temp directory as well.

Remember to launch as an administrator or the Intunewinapputil will get very upset

Any comments, feedback or suggestions most welcome in the comments.

192 thoughts on “Automating App Deployment with Winget and Intune”

  1. Thanks Andrew. This could be very useful. I’ve tested using different PowerShell versions but haven’t been able to get working. I think with PS5 ISE, it flashes open and closes instantly, but cant confirm. I have left the
    ——————————————
    With PS5 ISE i get message: (it doenst go passed this screen after leaving for 30 mins. I do get both AD prompts.)
    Transcript started, output file is C:\Users\J~1.NEW\AppData\Local\Temp\intune-12102022.log
    Installing Intune modules if required (current user scope)
    AZ Ad Preview Module Already Installed
    Directory already existed

    Directory: C:\temp
    Mode LastWriteTime Length Name
    d—– 12/10/2022 10:22 361-2210122234
    winget already installed
    Checking for AzureAD module…

    Account : [email protected]
    Environment : AzureCloud
    Tenant : 16a4dc93-e50d-
    TenantId : 16a4dc93-e50d-
    TenantDomain : tenant.onmicrosoft.com
    ——————————————
    With PS7 via Win Terminal i get message: (it doenst go passed this screen after leaving for 30 mins. I do get both AD prompts.)

    Directory: C:\temp
    Mode LastWriteTime Length Name
    —- ————- —— —-
    d—– 12/10/2022 10:18 258-2210121844
    winget already installed
    Checking for AzureAD module…

    Account : [email protected]
    Environment : AzureCloud
    Tenant : 16a4dc93-e50d-xxx
    TenantId : 16a4dc93-e50d-xxxx
    TenantDomain : tenant.onmicrosoft.com
    ——————————————
    With PS7 i get message:
    Checking for AzureAD module…
    Authorization Access Token is null, please re-run authentication…

    Reply
  2. Hi Andrew,

    Super cool idea….
    Just tried your script.
    Content is created in C:\temp\random_number but it creates for example a directory called “7-zip space, space, space, space, space…. 7-zip.7zip” with a detection7-Zip, install7-Zip and uninstall7-Zip with many spaces… and then it fails…
    How can we fix this?

    Reply
    • Hi, I have a trim() command on the application name which should remove the whitespace. Any chance you can send me the transcript output so I can have a look?
      Which apps did you test with? I’ll do some testing my end as well

      Reply
  3. Your script Doesn’t seem to support Azure MFA so companies that Force MFA it doesn’t to function as needed

    You can do the following to get your tokens with MFA Clams on them:

    # Get token for MS Graph by prompting for MFA
    $MsResponse = Get-MSALToken -Scopes @(“https://graph.microsoft.com/.default”) -ClientId “1b730954-1685-4b74-9bfd-dac224a7b894” -RedirectUri “urn:ietf:wg:oauth:2.0:oob” -Authority “https://login.microsoftonline.com/common” -Interactive -ExtraQueryParameters @{claims='{“access_token” : {“amr”: { “values”: [“mfa”] }}}’}

    # Get token for AAD Graph
    $AadResponse = Get-MSALToken -Scopes @(“https://graph.windows.net/.default”) -ClientId “1b730954-1685-4b74-9bfd-dac224a7b894” -RedirectUri “urn:ietf:wg:oauth:2.0:oob” -Authority “https://login.microsoftonline.com/common”

    #Connect to Azure AD
    Connect-AzureAD -AadAccessToken $AadResponse.AccessToken -MsAccessToken $MsResponse.AccessToken -AccountId: $AccountID -tenantId: $TenantID

    Reply
  4. It seems it does upload and does some graph functions but it does die out due to it being unable to connect to Azure AD modules I selected a Random Application to upload to test out the script

    Creating AAD Groups for BatteryMon
    New-AzureADMSGroup : You must call the Connect-AzureAD cmdlet before calling any other cmdlets.
    At C:\Program Files\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:2545 char:12
    + $grp = New-AzureADMSGroup -DisplayName $groupname -Description $g …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [New-AzureADMSGroup], AadNeedAuthenticationException
    + FullyQualifiedErrorId : Microsoft.Open.Azure.AD.CommonLibrary.AadNeedAuthenticationException,Microsoft.Open.MSGr
    aphBeta.PowerShell.NewMSGroup

    New-AzureADMSGroup : You must call the Connect-AzureAD cmdlet before calling any other cmdlets.
    At C:\Program Files\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:2545 char:12
    + $grp = New-AzureADMSGroup -DisplayName $groupname -Description $g …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [New-AzureADMSGroup], AadNeedAuthenticationException
    + FullyQualifiedErrorId : Microsoft.Open.Azure.AD.CommonLibrary.AadNeedAuthenticationException,Microsoft.Open.MSGr
    aphBeta.PowerShell.NewMSGroup

    another Error here form a graph call
    Creation Proactive Remediation for BatteryMon
    Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
    At C:\Program Files\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:2670 char:29
    + … ssign = Invoke-RestMethod -Uri $uri -Headers $authToken -Method P …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
    eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

    Then at the end

    Assigning Groups
    Invoke-RestMethod : The remote server returned an error: (400) Bad Request.
    At C:\Program Files\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:2796 char:5
    + Invoke-RestMethod -Uri $uri -Headers $authToken -Method Post -Bod …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
    eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

    It did however upload the Application

    Reply
  5. I was able to fix the script by changing the connect-AzureAD -credential $user line to the following

    ##Get Credentials
    # Get token for MS Graph by prompting for MFA
    $MsResponse = Get-MSALToken -Scopes @(“https://graph.microsoft.com/.default”) -ClientId “1b730954-1685-4b74-9bfd-dac224a7b894” -RedirectUri “urn:ietf:wg:oauth:2.0:oob” -Authority “https://login.microsoftonline.com/common” -Interactive -ExtraQueryParameters @{claims='{“access_token” : {“amr”: { “values”: [“mfa”] }}}’}

    # Get token for AAD Graph
    $AadResponse = Get-MSALToken -Scopes @(“https://graph.windows.net/.default”) -ClientId “1b730954-1685-4b74-9bfd-dac224a7b894” -RedirectUri “urn:ietf:wg:oauth:2.0:oob” -Authority “https://login.microsoftonline.com/common”

    $userUpn = New-Object “System.Net.Mail.MailAddress” -ArgumentList $User

    $TenantID = $userUpn.Host
    #Connect to Azure AD
    Connect-AzureAD -AadAccessToken $AadResponse.AccessToken -MsAccessToken $MsResponse.AccessToken -AccountId: $cred.UserName -tenantId: $TenantID

    This allowed it to function with MFA Clams with no issues. You might be able to drop that entire user entry box and pull the data using the above token info that you are prompting for just didnt have time to work it out.

    Reply
  6. I’m having issues with intune failing to detect the apps correctly when they are installed using the app and dection script. Any suggestions?

    Reply
  7. Thank you for the quick reply.

    I will try again using the new version. I am also having issues with the script successfully uploading the application to intune. I am receiving an error when the scipt get to the “uploading files to intune” and “Assigning Groups”. I have tried deploy-winget-win32-multiple-graphonly and deploy-winget-win32-multiple-multiple. and they both error at the same spot. Any suggestions on that? Can share error via email if that would help.

    Thanks for your hard work on this module.

    Reply
  8. Hello, I wasn’t able to locate your email so I will post it here. I am having issues with the detection script as mentioned above and also having the below error. Any help would be appreciated.

    UploadAzureStorageChunk : PUT https://mmcswda01.blob.core.windows.net/c66ccf2c-dc7e-4486-a9fe-7938db6d1679/8aded0a0-fe7 c-45fa-a740-25db6bc75d8d/754af1ea-b3c2-4d7a-b858-c292dd58b205.intunewin.bin?sv=2016-05-31&sr=b&si=-2056882926&sig=mihso R0kk8IwpQsG5wcrlUTVW%2B99OjXdZmbL%2B58%2FP%2F8%3D&comp=block&blockid=MDAwMA== At C:\deploy-winget-win32-multiple.ps1:453 char:13 + UploadAzureStorageChunk $sasUri $id $bytes + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,UploadAzureStorageChunk UploadAzureStorageChunk : The remote server returned an error: (403) Forbidden. At C:\deploy-winget-win32-multiple.ps1:453 char:13 + UploadAzureStorageChunk $sasUri $id $bytes + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,UploadAzureStorageChunk Invoke-UploadWin32Lob : Aborting with exception: System.Net.WebException: The remote server returned an error: (403) Forbidden. at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request) at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord() At C:\deploy-winget-win32-multiple.ps1:2439 char:18 + … appupload = Invoke-UploadWin32Lob -SourceFile “$appfile” -DisplayName … + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Invoke-UploadWin32Lob 0 Grammarly for Microsoft┬« Office Suite Created and uploaded VERBOSE: Assigning Groups VERBOSE: POST https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/6a3bc1f9-4fc2-4c42-a8be-2fc3d039d0c0/assign with 670-byte payload VERBOSE: received 797-byte response of content type application/json Invoke-MgGraphRequest : POST https://graph.microsoft.com/beta/deviceAppManagement/mobileApps/6a3bc1f9-4fc2-4c42-a8be-2fc3d039d0c0/assign HTTP/1.1 400 Bad Request Transfer-Encoding: chunked Vary: Accept-Encoding Strict-Transport-Security: max-age=31536000 request-id: dfb38651-04b3-495d-a869-abdb95147ca6 client-request-id: dfb38651-04b3-495d-a869-abdb95147ca6
    x-ms-ags-diagnostic: {“ServerInfo”:{“DataCenter”:”Canada
    East”,”Slice”:”E”,”Ring”:”2″,”ScaleUnit”:”002″,”RoleInstance”:”QB1PEPF00002F9E”}}
    Date: Tue, 22 Nov 2022 16:46:50 GMT
    Content-Encoding: gzip
    Content-Type: application/json
    {“error”:{“code”:”BadRequest”,”message”:”{\r\n \”_version\”: 3,\r\n \”Message\”: \”Invalid operation: app’s
    PublishingState is not ‘Published’. – Operation ID (for customer support): 00000000-0000-0000-0000-000000000000 –
    Activity ID: dfb38651-04b3-495d-a869-abdb95147ca6 – Url: https://fef.msua01.manage.microsoft.com/AppLifecycle_2211/Stat
    elessAppMetadataFEService/deviceAppManagement/mobileApps(‘6a3bc1f9-4fc2-4c42-a8be-2fc3d039d0c0’)/microsoft.management.s
    ervices.api.assign?api-version=5022-09-01\”,\r\n \”CustomApiErrorPhrase\”: \”\”,\r\n \”RetryAfter\”: null,\r\n
    \”ErrorSourceService\”: \”\”,\r\n \”HttpHeaders\”: \”{}\”\r\n}”,”innerError”:{“date”:”2022-11-22T16:46:51″,”request-id
    “:”dfb38651-04b3-495d-a869-abdb95147ca6″,”client-request-id”:”dfb38651-04b3-495d-a869-abdb95147ca6″}}}
    At C:\deploy-winget-win32-multiple.ps1:2413 char:5
    + Invoke-MgGraphRequest -Uri “https://graph.microsoft.com/beta/devi …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (Method: POST, R…ication/json
    }:HttpRequestMessage) [Invoke-MgGraphRequest], HttpResponseException
    + FullyQualifiedErrorId : InvokeGraphHttpResponseException,Microsoft.Graph.PowerShell.Authentication.Cmdlets.Invok
    eMgGraphRequest

    Reply
  9. Hi Andrew

    Im getting the following error. Any ideas, im not much of a powershell person!

    Mode LastWriteTime Length Name
    —- ————- —— —-
    d—– 28/11/2022 08:40 249-2211284049
    winget already installed
    Connect-MgGraph : User canceled authentication.
    At C:\temp\scripts\DeployWinGetMultiple.ps1:2457 char:1
    + Connect-MgGraph -Scopes DeviceManagementApps.ReadWrite.All, DeviceMan …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Connect-MgGraph], MsalClientException
    + FullyQualifiedErrorId : Microsoft.Graph.PowerShell.Authentication.Cmdlets.ConnectMgGraph
    Connect-MgGraph : User canceled authentication.
    At C:\temp\scripts\DeployWinGetMultiple.ps1:2457 char:1
    + Connect-MgGraph -Scopes DeviceManagementApps.ReadWrite.All, DeviceMan …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Connect-MgGraph], MsalClientException
    + FullyQualifiedErrorId : Microsoft.Graph.PowerShell.Authentication.Cmdlets.ConnectMgGraph

    Reply
    • Hi Simon,
      That error looks like the authentication didn’t work, you should get a popup box with a browser window to authenticate and approve the Graph connection. It might be worth looking for Applocker settings for both this and your Winget issue

      Reply
  10. Hello Andrew,
    it looks that the output in gridview is not formatted the right way. The values for Name and ID are in the same column, the column ID is empty. Therefor the variables are not filled.

    Reply
    • Hi Jonas,

      Not with this script because you can’t wildcard search on msstore apps so I can’t get the grid-view output.

      I have a new post going live tomorrow with some PowerShell functions you can use for msstore apps though

      Reply
  11. Hi Andrew

    I’m facing an error with this script. I think script failed to get winget packages.

    OS: Windows 11 22H2 (22623.1037)
    PowerShell: 7.3.1
    winget: v1.4.3132-preview

    Log

    Microsoft Graph Already Installed
    Directory already existed

    Directory: C:\temp

    Mode LastWriteTime Length Name
    —- ————- —— —-
    d—- 2022-12-22 오전 9:28 65-2212222808
    winget already installed
    Welcome To Microsoft Graph!

    Write-Error: C:\Users\rubik\Documents\PowerShell\Scripts\deploy-winget-win32-multiple.ps1:1345
    Line |
    1345 | … $List = Invoke-WinGetCommand -WinGetArgs $WinGetArgs -IndexTitles …
    | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    | No results were found.

    Write-Error: C:\Users\rubik\Documents\PowerShell\Scripts\deploy-winget-win32-multiple.ps1:1345
    Line |
    1345 | … $List = Invoke-WinGetCommand -WinGetArgs $WinGetArgs -IndexTitles …
    | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    | No results were found.

    ClientId : (DELETED)
    TenantId : (DELETED)
    CertificateThumbprint :
    Scopes : {DeviceManagementApps.ReadWrite.All, DeviceManagementConfiguration.ReadWrite.All, email, Group.
    ReadWrite.All…}
    AuthType : Delegated
    AuthProviderType : InteractiveAuthenticationProvider
    CertificateName :
    Account : (DELETED)
    AppName : Microsoft Graph PowerShell
    ContextScope : CurrentUser
    Certificate :
    PSHostVersion : 7.3.1

    Reply
    • Hi Sanghyeon, thanks for your message. I’ve just installed that version of Winget on my 22H2 machine and can’t seem to replicate the issue. Any chance you can confirm if you have any language packs installed? I’ve seen that cause problems before

      Thanks

      Reply
  12. I am not able to get the packages to load. When I launch the script, it just sits at Loading Winget Packages and does not do anything else.

    Reply
  13. Hi Andrew,
    I have used the Script and replaced all my Store Apps with this Script now. I have had no issues in over 2 weeks. Everything is the way it should be. I just replaced Group names and added “Test” in the Group names for my Testing initially as I already have App groups created.

    Thank you for the hard work.

    Reply
  14. Yes, Andrew. I am a very big fan of Automation too. I am working towards Automating Intune standard config for any new client in 30 minutes. Done enough testing. Your Script made life easier for Apps. For Config Profiles and Admin Templates etc, I use Micke Karlsson Tool. Configure Demo Tenant. Export it without Assignment. Import it to new Tenant. Do the assignment. Make any Modification (Tenant ID etc if needed), now Add apps using Andrew’s Script. Do Customised Modifications if needed on the Tenant and done.

    Reply
  15. So, I have replaced your old script with the new one Github. Getting this error on any App I try to install. Any Ideas?

    Directory: C:\temp\186-2301314527

    Mode LastWriteTime Length Name
    —- ————- —— —-
    d—– 31/01/2023 14:45 Microsoft.DotNet.Framework.Developâ
    Directory c:\temp\186-2301314527\\Microsoft.DotNet.Framework.Developâ Created
    VERBOSE: Creating AAD Groups for .NET Framework
    New-MgGroup : One or more errors occurred.
    At line:2205 char:5
    + $grp = New-MgGroup -DisplayName $groupname -Description $groupdes …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [New-MgGroup_CreateExpanded1], AggregateException
    + FullyQualifiedErrorId : System.AggregateException,Microsoft.Graph.PowerShell.Cmdlets.NewMgGroup_CreateExpanded1

    Reply
    • Can you try and app with a shorter name? I’ve seen this before with some MS apps where it truncates the name and adds random special characters.
      If it works with shorter apps, I’ll see if I can add some logic in

      Reply
  16. Andrew,
    Firstly, thank you for putting this together, it is absolutely amazing!
    I have tried a few apps into a demo tenant and they are working as expected. I then apply additional descriptions, app icons and rename the groups to meet a convention (which is minimal compared to the time you are saving me)

    I am having an issue in deploying the apps to an Autopilot enrolled AAD only device – basically no apps deploy. I still need to troubleshoot it mire, authenticating as admin to read C:\Windows\Temp\
    Reading your comment that the user or an admin might need to run “winget list –accept-package-agreements” – I have tried deploying a Script to these devices with no luck. has anyone else needed to do this to managed devices that have never used winget before? It really is a prerequisite for all this to work, from what I am seeing

    Reply
    • Hi Shane,

      Glad you’re finding it useful.
      The install command for the apps include –accept-package-agreements and –accept-source-agreements so that shouldn’t be a blocker any more.
      Are these Windows 10 or Windows 11 machines and do they have Winget pre-installed?
      If you let me know which OS version and which app, I’ll try to replicate your setup and see what I can find

      Reply
  17. Hi Andrew,

    Thank you so much for creating this script. its fantastic and seems to work most of the time really well.

    I will say though, i am having problems with it creating groups and assigning it to apps if the app has a space in its name.

    For example, ‘Jabra Direct’. the app will upload create everything correctly apart from the install and uninstall groups. im guessing this is because graph doesnt like spaces?

    anyway to fix this? try replicating this for yourself and you will see.

    here is the error i received…

    “VERBOSE: Creating AAD Groups for Jabra Direct
    New-MgGroup : Invalid value specified for property ‘mailNickname’ of resource ‘Group’.
    At C:\Users\RDavies\Downloads\public-main\public-main\Powershell Scripts\Intune\deploy-winget-win32-multiple.ps1:2205 char:5
    + $grp = New-MgGroup -DisplayName $groupname -Description $groupdes …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: ({ body = Micros…ftGraphGroup1 }:f__AnonymousType1`1) [New-MgGroup_CreateExpanded1], RestException`1
    + FullyQualifiedErrorId : Request_BadRequest,Microsoft.Graph.PowerShell.Cmdlets.NewMgGroup_CreateExpanded1
    New-MgGroup : Invalid value specified for property ‘mailNickname’ of resource ‘Group’.
    At C:\Users\RDavies\Downloads\public-main\public-main\Powershell Scripts\Intune\deploy-winget-win32-multiple.ps1:2205 char:5
    + $grp = New-MgGroup -DisplayName $groupname -Description $groupdes …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: ({ body = Micros…ftGraphGroup1 }:f__AnonymousType1`1) [New-MgGroup_CreateExpanded1], RestException`1
    + FullyQualifiedErrorId : Request_BadRequest,Microsoft.Graph.PowerShell.Cmdlets.NewMgGroup_CreateExpanded1”

    Reply
  18. Hi again Andrew.

    I just want to say i have actually managed to resove this myself by adding a very simple work around in your script.

    Just posting so others can see if they have issues:

    during the function ‘new-aadgroups’ in the script, I add the following after the ‘switch ($grouptype)’

    $appname = $appname -replace ‘ ‘,’_’

    so instead of your code which is:
    switch ($grouptype) {
    “install” {
    $groupname = “LFFUK-Apps-Install-” + $appname
    $nickname = “LFFUK-Apps-Install-” + $appname
    $groupdescription = “Group for installation and updating of $appname application”
    }
    “uninstall” {
    $groupname = “LFFUK-Apps-Uninstall-” + $appname
    $nickname = “LFFUK-Apps-Uninstall-” + $appname
    $groupdescription = “Group for uninstallation of $appname application”
    }
    }

    i add the following in **

    switch ($grouptype) {
    “install” {
    **$appname = $appname -replace ‘ ‘,’_’**
    $groupname = “LFFUK-Apps-Install-” + $appname
    $nickname = “LFFUK-Apps-Install-” + $appname
    $groupdescription = “Group for installation and updating of $appname application”
    }
    “uninstall” {
    **$appname = $appname -replace ‘ ‘,’_’**
    $groupname = “LFFUK-Apps-Uninstall-” + $appname
    $nickname = “LFFUK-Apps-Uninstall-” + $appname
    $groupdescription = “Group for uninstallation of $appname application”
    }
    }

    not sure if its worth adding into your code?

    Reply
    • Hi Ryan,

      Thanks for pointing this out (and glad you’re finding it useful).

      It’s failing on the MailNicknam which should be set to the $appid rather than the $appname (if you’re using v2.0.7)

      When you made the changes to add a prefix, could it be you copy and pasted the name rather than the ID for that one?

      Reply
  19. Ahh yes, you are right, I may have done this. any affects if i leave it like this? or do you recommend I change it back to $appid?

    Reply
  20. Hi Andrew

    first of all thank you for your work. you help us sys admins a lot!
    Some how when i run you script every thing works fine, until it gets stuck in “Loading Winget Packages” from there it is not Processing any dot.

    could you maybe help me out with a hint?

    regards

    Reply
    • Hi,
      Glad you’re finding it useful! First thing is to load up PowerShell/Command prompt and type “Winget List”, it might be you need to accept the license agreement.
      Make sure you don’t have anything which would block the gridview popup window as well

      Reply
  21. Hi,

    i found two syntax errors in the script, so that the install and uninstall ps1 did not work.

    It should read correctly.

    function new-installscript:
    &`$winget install –id `$appid –silent –force –accept-package-agreements –accept-source-agreements –scope machine –exact | out-null

    function new-uninstallscript
    &`$winget uninstall –id `$appid –silent –force –accept-package-agreements –accept-source-agreements

    The ` missed before the variable $appid.

    As always.
    Variables won’t. Constants aren’t.

    Kind Regards,
    LEM

    Reply
  22. Hi,
    with me the script didn’t work without the backtick before them.
    After I added them, it functions perfectly.

    Different behaviour on two systems? Any ideas?

    Reply
  23. Here you are.

    without backtick – Name: install.ps1
    —-
    $ResolveWingetPath = Resolve-Path “C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe”
    if ($ResolveWingetPath){
    $WingetPath = $ResolveWingetPath[-1].Path
    }

    $Winget = $WingetPath + “\winget.exe”
    &$winget install –id –silent –force –accept-package-agreements –accept-source-agreements –scope machine –exact | out-null
    —-

    backtick – Name: install7zip.7zip.ps1
    —-
    $ResolveWingetPath = Resolve-Path “C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe”
    if ($ResolveWingetPath){
    $WingetPath = $ResolveWingetPath[-1].Path
    }

    $Winget = $WingetPath + “\winget.exe”
    &$winget install –id $appid –silent –force –accept-package-agreements –accept-source-agreements –scope machine –exact | out-null
    —-

    As you can see, contrary behaviour.

    Reply
    • Neither of those will work, both are missing the AppID, has anything else changed in the script?
      This is what I get:
      $ResolveWingetPath = Resolve-Path “C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe”
      if ($ResolveWingetPath){
      $WingetPath = $ResolveWingetPath[-1].Path
      }

      $Winget = $WingetPath + “\winget.exe”
      &$winget install –id 7zip.7zip –silent –force –accept-package-agreements –accept-source-agreements –scope machine –exact | out-null

      Are you using the German language pack? I’ve seen that cause issues before

      Reply
  24. That must be the cause.
    Indeed, am I using the german language pack.

    Do you know a workaround for the issue?

    Many thanks in advance.

    Reply
  25. Hi,

    I have tested and quotation marks do the trick.

    &`$winget install –id “$appid” –silent –force –accept-package-agreements –accept-source-agreements –scope machine –exact | out-null

    and you get in install.ps1

    &$winget install –id “7zip.7zip” –silent –force –accept-package-agreements –accept-source-agreements –scope machine –exact | out-null

    in install7zip.7zip.ps1

    Is that a solution in your opinion?

    Kind regards

    Reply
  26. The interesting fact was, that the install and uninstall schripts were affected und the detection script wasn’t affected.

    Thanks for helping!

    Reply
  27. hi , i am getting this error when it was load the graph and winget, any idea what could be wrong? thanks in advance
    Invoke-WinGetCommand : No results were found.
    At C:\Program Files\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:1379 char:17
    + … $List = Invoke-WinGetCommand -WinGetArgs $WinGetArgs -IndexTitles …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (System.String[]:String[]) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Invoke-WinGetCommand

    Reply
  28. Actually it was not display the gridview for me select anything and just throw that error. was that someting that my environment that is not allow or blocking the graph to display the gradview ?

    Reply
  29. power shell ISE is there in the machine, everything was loading till to “welcome to MS graph”-there is not gridview, then it went to the command to invoke-winget….
    Welcome To Microsoft Graph!
    Invoke-WinGetCommand : No results were found.
    At C:\Temp\deploy-winget-win32-multiple.ps1:1379 char:17
    + … $List = Invoke-WinGetCommand -WinGetArgs $WinGetArgs -IndexTitles …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (System.String[]:String[]) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Invoke-WinGetCommand

    ClientId : 1xxxxx
    TenantId : exxxxxxxxxx
    CertificateThumbprint :
    Scopes : {DeviceManagementApps.ReadWrite.All, DeviceManagementConfiguration.ReadWrite.All, Directory.AccessAsUser.All, email…}
    AuthType : Delegated
    AuthProviderType : InteractiveAuthenticationProvider
    CertificateName :
    Account : [email protected]
    AppName : Microsoft Graph PowerShell
    ContextScope : CurrentUser
    Certificate :
    PSHostVersion : 5.1.19041.2673

    👍 Selected apps have been deployed to Intune

    Reply
    • You might need to add the functions and then try running just the gridview bit and see what happens.
      At that point it’s just searching for all winget apps and returning a list

      Reply
  30. Hi, this should be where the loading is started
    so it seem that it cannot do the search all function
    $packs = find-wingetpackage ‘””‘

    Invoke-WinGetCommand : No results were found.
    At line:116 char:17
    + … $List = Invoke-WinGetCommand -WinGetArgs $WinGetArgs -IndexTitles …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (System.String[]:String[]) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Invoke-WinGetCommand

    If i do it with single item, it was ok
    find-wingetpackage ‘”git”‘ | out-gridview

    Reply
  31. i found that it was issue when i run it using my admin account , but it was now working fine if i used my normal account . it seem tha winget is not doing well when it was using the admin account

    Reply
  32. Hi Andrew
    The automation really cool. thanks for the great work!
    Btw, do you know why uninstall will be failing? as i can see , all the apps is install with system context , it was installing nicely , but when i try to add the devcie to the uninstall, it was failing
    Example , Notepad++
    i wonder do you face any issue when assigned the uninstall using intune?
    Thank you

    Reply
  33. ok, the uninstall does not take this 🙂
    argument name was not recognized for the current command: ‘–accept-package-agreements’

    Reply
  34. Hello Andrew,
    Great work on this script. I don’t have full permissions to Azure but I was able to grab the apps that I needed and I’m going to manually add them to endpoint.
    In my testing I was able to create the apps but I’m getting this issue in company portal.
    Download Pending….
    Your device is syncing and will begin your download shortly.

    My install line has powershell.exe -ExecutionPolicy Bypass -File .\filename.ps1
    My uninstall line has this as well.
    Any ideas how I could troubleshoot this?

    Reply
    • Hi Peter,
      That’s normally a network issue of some sort which is blocking the file from downloading. It lives in an Azure blob, downloads to the machine and then extracts itself (and installs). Are you behind any firewalls or VPNs?

      Reply
  35. Hello Andrew,
    Yes we are behind a firewall. Our manually created apps work. I can manually install that software via a powershell prompt but when I try to install it via Company Portal it just hangs there. I will check with the firewall guys to see if they can monitor what is going on.
    Thank you for the response.
    Peter

    Reply
  36. Absolutely amazing script Andrew. Worked first time for me. Been meaning to have a play deploying via Winget.

    Any ideas if this would work at pre-provisioning stage, I might need to do some testing as unsure if winget is available till after the user logs in for the first time?

    Thanks for this!

    Reply
    • Hi Matt,
      You could package Winget as a Win32 app and then set it as a pre-requisite for any apps you want deployed during ESP. If you deploy any new store apps, they will push Winget to the device as well, but we wouldn’t be able to control at what stage for those

      Reply
  37. Cool, might do some testing then. I’m sure we’re all waiting for the day when we cant control app install order especially during ESP. It’s like the only thing really missing at the moment!

    Reply
  38. Hi Andrew,
    Thank you very much for your script. It’s really helpful.
    But I’m having some issues,
    your script runs and shows me all the apps in winget and I can choose the app and it makes the intunewin and all other files.
    but it is not asking me to login to intune and it’s not uploading the file.
    Do you have any idea, what I’m doing wrong?
    Regards,
    Rony

    Reply
    • Hi Rony,
      That’s strange, it should connect before creating anything.
      Can you try running this in a new console window and see what happens?

      Select-MgProfile -Name Beta
      Connect-MgGraph -Scopes DeviceManagementApps.ReadWrite.All, DeviceManagementConfiguration.ReadWrite.All, Group.ReadWrite.All, GroupMember.ReadWrite.All, openid, profile, email, offline_access

      Thanks

      Andrew

      Reply
  39. Hi Andrew

    Thank you for your great work.

    I have deployed the apps successfully to Intune with detectionscripts.
    My issue is that when i assign the app to a group (UserGroup) it show successfull in intune but the app is not installed.

    Before a big effort i wanted to ask you first.

    Regards,
    snn

    Reply
    • Hi,
      On a machine, can you type “winget list” at the command line and see if the app shows up there?
      The detection script looks for the app ID in the returned output
      If it’s showing, the app says it’s installed so we then need to look at why you can’t see it in the UI

      Reply
  40. Hi Andrew

    I don’t see the app in winget list.. I also tried to make sure that i install it trough the company Portal to make sure it installs.

    What i have is the output of the install.ps1 for Mozilla Firefox:
    ———————————————————————————
    $ResolveWingetPath = Resolve-Path “C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe”
    if ($ResolveWingetPath){
    $WingetPath = $ResolveWingetPath[-1].Path
    }

    $Winget = $WingetPath + “\winget.exe”
    &$winget install –id “” –silent –force –accept-package-agreements –accept-source-agreements –scope machine –exact | out-null
    ———————————————————————————

    This Path is for every app the same: C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe

    But when i look in this path it doesn’t exist.

    regards,

    Reply
  41. It seems like the $appid is empty.. i don’t see it anywhere.
    the deployment to intune is from a windows 11 (english) OS

    Reply
    • Can I check with version of the script you are running and which version of Winget on the machine you are creating the packages on? I’ve just tested Firefox on my machine and it has populated ok

      Reply
  42. Hi Andrew

    Here is the version of your Script:

    Deploying Computer winget Version: v1.4.10173
    Receiving Computer winget Version: v1.4.10173

    Reply
  43. Yes it shows up but the column looks like is not in line. App ID shows in Name and when i try to filter with id it shows empty

    Reply
  44. Hi Andrew

    we are facing the issue that the packages which we install only works with the Admin Credentials…

    Our deployment:
    – Apps are deployed with the script
    – Detection and Scripts are correct
    – We deploy the apps to a user Group which are non admins on the devices -> Fails

    Test:
    – everything same -> Admin User enrollment and it works

    can you help me out please?

    Regards

    Reply
  45. “C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe”
    This path can’t be find…

    When i check winget from the current user -> it is there
    When i check winget from elevated -> it is not available

    Reply
  46. Hi! This is great thank you!

    So does these apps update automatically within intune or do we need to redeploy new version every time?

    Whilst I am here what is the best way to update apps Supersedence or just deploy new version of app

    Reply
    • As long as you are licensed for them, the apps will update using remediations and Winget.

      For your second question, it largely depends on the app, I prefer supersedence as it gives a bit more control over whether it updates, or removes and re-installs

      Reply
  47. Hi,

    Any app I try to download I am getting “The application was not detected after installation completed successfully” message and app doesnt install

    Any ideas?

    Reply
  48. Hi Andrew,

    The apps are team viewer and LEGO® MINDSTORMS® Education EV3 Classroom

    Regarding install / detection I havent made any changes just used the ones provided. Is there anything in particular I need to look for in the install and detection scripts?

    Reply
  49. This is the error:

    & : The term ‘\winget.exe’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
    spelling of the name, or if a path was included, verify that the path is correct and try again.
    At C:\temp\866-2306284920\TeamViewer.TeamViewer\installTeamViewer.TeamViewer.ps1:7 char:6
    + &$winget install –id “TeamViewer.TeamViewer” –silent –force — …
    + ~~~~~~~
    + CategoryInfo : ObjectNotFound: (\winget.exe:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Reply
  50. Yes the command looks okay, however I havent had a working install yet. Only tired team viewer and the lego mindstorm app

    Here is the command:

    $ResolveWingetPath = Resolve-Path “C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe”
    if ($ResolveWingetPath){
    $WingetPath = $ResolveWingetPath[-1].Path
    }

    $Winget = $WingetPath + “\winget.exe”
    &$winget install –id “TeamViewer.TeamViewer” –silent –force –accept-package-agreements –accept-source-agreements –scope machine –exact | out-null

    within the installteamviewer.teamviewer.ps1

    Reply
  51. I figured it out, it seems all these apps have a “\” in front of winget when its meant to be simply “winget” within the install script, could this be fixed?

    Reply
  52. Hi Andrew,
    I’ve just grabbed the latest version of your script. I am getting an error “The Win32LobApp must have at least one detection rule specified”

    It creates folders for the selected apps in C:\temp with all PS1 scripts and intunewin, but looks like it’s having troubles creating an app and groups.

    The full dump of the error is below:

    New-MgDeviceAppMgtMobileApp : { “_version”: 3, “Message”: “The Win32LobApp must have at least one detection rule specified. – Operation ID (for customer support): 00000000-0000-0000-0000-000000000000 – Activity ID: 03e31d9d-ddd8-49d2-8b33-68643970603e – Url: https://fef.msua01.mana ge.microsoft.com/AppLifecycle_2307/StatelessAppMetadataFEService/deviceAppManagement/mobileApps?api-version=2023-05-18″ , “CustomApiErrorPhrase”: “”, “RetryAfter”: null, “ErrorSourceService”: “”, “HttpHeaders”: “{}” } Status: 400 (BadRequest) ErrorCode: BadRequest Date: 2023-07-21T17:34:48 Headers: Transfer-Encoding : chunked Vary : Accept-Encoding Strict-Transport-Security : max-age=31536000 request-id : 41cdfa54-77a3-4702-9130-bf48477e29ec client-request-id : 03e31d9d-ddd8-49d2-8b33-68643970603e x-ms-ags-diagnostic : {“ServerInfo”:{“DataCenter”:”South Central US”,”Slice”:”E”,”Ring”:”5″,”ScaleUnit”:”001″,”RoleInstance”:”SA2PEPF000010F6″}} Date : Fri, 21 Jul 2023 17:34:47 GMT At C:\Program Files\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:1254 char:9 + $mobileApp = New-MgDeviceAppMgtMobileApp -BodyParameter ($mob … + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: ({ body = Micros…raphMobileApp }:f__AnonymousType72`1) [New-MgDevi ceApp…obileApp_Create], Exception + FullyQualifiedErrorId : BadRequest,Microsoft.Graph.PowerShell.Cmdlets.NewMgDeviceAppManagementMobileApp_Create

    Reply
  53. I’m getting the same “The Win32LobApp must have at least one detection rule specified.” message with Zoom, Notepad++, Slack.

    Also, I think Function Get-ScriptVersion is pointing to a different script?

    Reply
  54. Thanks Andrew! Perfect, fixed the issues and the scriptversion message. If its helpful I can share the logs, but I think you have it.

    Reply
  55. Im having a terrible time with winget inside proactive remediation scripts.
    Our users cant run cmd or powershell and we run all installs in the sytem Contect.

    All users are on Windows 11 22h2

    I have half a dozen working which I thought was as a rsult of installing APP installer into the system context, but it doesnt seem to have made a difference to the larger number of users.

    I simply get a failed and if I investigate the intune logs I see a powershell script execution timed out. timeout = 3600 seconds.

    I see mixed results accross different tenancies. Somewhere the same script works and others where they all fail.

    I know Im missing something but I can figure out what. Any ideas happly accepted

    Reply
  56. Heres the script

    $ResolveWingetPath = Resolve-Path “C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\winget.exe”
    if ($ResolveWingetPath){
    $WingetPath = $ResolveWingetPath[-1].Path
    }

    $Wingetpath = Split-Path -Path $WingetPath -Parent
    cd $wingetpath
    $updates =.\winget.exe upgrade

    If ($Updates[-1] -match ‘No installed package’) {
    Write-host “No packages availble for updating”
    exit 0
    }else {
    Write-host “The following packages need upgrading:” $Updates[-5..-1]
    exit 1
    }

    Reply
  57. Unfortunately this ended without reolving winget

    The expression after ‘&’ in a pipeline element produced an object that was not valid. It must result in a command name, a script block, or a CommandInfo object. At C:\WINDOWS\IMECache\HealthScripts\59f76783-f7c0-4ae6-94a5-6b055d7930db_1\remediate.ps1:13 char:2 + &$winget upgrade –all –force –silent + ~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : BadExpression

    I suspect my issue is all tied around running winget in the system conetxt (though I havent worked out why it works for some but not all)

    Im currently running it on a new Laptop inthe system context (via Psexec -s powershell.exe) to test and the original script seems to work OK.

    Ill see how it goes when its put in the proactve script group

    Reply
  58. Whats the chances is the acceptance line. and because that failes it dosent run the remdiation part?
    Can you by-pass the acceptance?

    The source requires the current machine’s 2-letter geographic region to be sent to the backend service to function properly (ex. “US”).

    Reply
  59. Hi Andrew

    It turns out the issue was that I needed to be running winget with the —-accept-source-agreements switch in the proactive scripts

    eg: winget upgrade –accept-source-agreements
    otherwise it wasnt running (The prompt “The source requires the current machine’s 2-letter geographic region to be sent to the backend service to function properly (ex. “US”).” was appearing when running in the system context.

    Its a little weird because I have some tenancies which weren’t having a problem and others that all failed to run.

    Thanks again for your assistance and for the good work that you do!

    Reply
  60. Hi Andrew,

    Great script!

    Currently have it running to some extent.
    It does the remediation and the group creation but no intunewin file in the temp directory or imported to intune. Just wondering if im missing anything

    Directory c:\temp\348-2311031314\\Docker.DockerDesktop Created
    VERBOSE: Creating AAD Groups for Docker Desktop
    Created 63146980-780d-4754-8ddc-49dfd1e60f70 for installing Docker Desktop
    Created 145d1ce8-3fc2-49b9-957a-1c0848e69d4e for uninstalling Docker Desktop
    VERBOSE: Creating Install Script for Docker Desktop
    Script created at c:\temp\348-2311031314\\Docker.DockerDesktop\installDocker.DockerDesktop.ps1
    VERBOSE: Creating Uninstall Script for Docker Desktop
    Script created at c:\temp\348-2311031314\\Docker.DockerDesktop\uninstallDocker.DockerDesktop.ps1
    VERBOSE: Creating Detection Script for Docker Desktop
    Script created at c:\temp\348-2311031314\\Docker.DockerDesktop\detectionDocker.DockerDesktop.ps1
    VERBOSE: Creation Proactive Remediation for Docker Desktop
    VERBOSE: POST https://graph.microsoft.com/beta/deviceManagement/deviceHealthScripts with 1557-byte payload
    VERBOSE: received 1826-byte response of content type application/json
    VERBOSE: POST https://graph.microsoft.com/beta/deviceManagement/deviceHealthScripts/ea4b973c-38e6-44f9-92a4-25a969bb8fc1/assign with 958-byte payload
    VERBOSE: received 0-byte response of content type
    Success
    Proactive Remediation Created and Assigned for Docker Desktop
    VERBOSE: Creating Intunewin File for Docker Desktop
    INFO Validating parameters
    INFO Validated parameters within 2 milliseconds
    INFO Removing temporary files
    ERROR System.IO.IOException: The handle is invalid.

    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    at System.Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
    at Microsoft.Management.Service.IntuneWinAppUtil.LogUtil.PrintProgress(AppContext context)
    at Microsoft.Management.Service.IntuneWinAppUtil.PackageUtil.CreatePackage(String folder, String setupFile, String outputFolder, String catalogFolder)
    at Microsoft.Management.Service.IntuneWinAppUtil.Program.Main(String[] args)
    Intunewin c:\temp\348-2311031314\\Docker.DockerDesktop\installDocker.DockerDesktop.intunewin Created
    VERBOSE: Uploading Docker Desktop to Intune
    VERBOSE: Testing if SourceFile ‘c:\temp\348-2311031314\\Docker.DockerDesktop\installDocker.DockerDesktop.intunewin’ Path is valid…
    Test-SourceFile : Source File ‘c:\temp\348-2311031314\\Docker.DockerDesktop\installDocker.DockerDesktop.intunewin’
    doesn’t exist…
    At C:\Program Files (x86)\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:1106 char:9
    + Test-SourceFile “$SourceFile”
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-SourceFile
    Test-SourceFile : Source File
    ‘c:\temp\348-2311031314\\Docker.DockerDesktop\installDocker.DockerDesktop.intunewin’ doesn’t exist…
    At C:\Program Files (x86)\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:1106 char:9
    + Test-SourceFile “$SourceFile”
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-SourceFile

    Test-SourceFile : ScriptHalted
    At C:\Program Files (x86)\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:1106 char:9
    + Test-SourceFile “$SourceFile”
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-SourceFile
    Test-SourceFile : ScriptHalted
    At C:\Program Files (x86)\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:1106 char:9
    + Test-SourceFile “$SourceFile”
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-SourceFile

    PS>TerminatingError(): “System error.”
    >> TerminatingError(): “System error.”
    >> TerminatingError(): “System error.”

    ClientId : 14d8*******
    TenantId : 57f**********
    Scopes : {Calendars.Read, CloudPC.ReadWrite.All, DeviceManagementApps.ReadWrite.All,
    DeviceManagementConfiguration.ReadWrite.All…}
    AuthType : Delegated
    TokenCredentialType : InteractiveBrowser
    CertificateThumbprint :
    CertificateSubjectName :
    Account : ***************
    AppName : Microsoft Graph Command Line Tools
    ContextScope : CurrentUser
    Certificate :
    PSHostVersion : 5.1.22621.2506
    ManagedIdentityId :
    ClientSecret :
    Environment : Global

    👍 Selected apps have been deployed to Intune

    Reply
  61. A super tool.

    But for some reason it has stopped working.
    It worked fine 2 weeks ago. But now it only creates the powershell scripts and the groups.
    I’m running the tool as administrator

    I get this from the powershell command:

    Mode LastWriteTime Length Name
    —- ————- —— —-
    d—– 13/11/2023 10.33 Fortinet.FortiClientVPN
    Directory c:\temp\932-2311133321\\Fortinet.FortiClientVPN Created
    Created 3ab46b34-5ee9-4260-b7a7-42085ec67a0f for installing FortiClient VPN
    Created eb602f91-fdb1-4ea4-9359-563cc29671e2 for uninstalling FortiClient VPN
    Script created at c:\temp\932-2311133321\\Fortinet.FortiClientVPN\installFortinet.FortiClientVPN.ps1
    Script created at c:\temp\932-2311133321\\Fortinet.FortiClientVPN\uninstallFortinet.FortiClientVPN.ps1
    Script created at c:\temp\932-2311133321\\Fortinet.FortiClientVPN\detectionFortinet.FortiClientVPN.ps1
    Success
    Proactive Remediation Created and Assigned for FortiClient VPN
    INFO Validating parameters
    INFO Validated parameters within 2 milliseconds
    INFO Removing temporary files
    ERROR System.IO.IOException: The handle is invalid.

    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    at System.Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
    at Microsoft.Management.Service.IntuneWinAppUtil.LogUtil.PrintProgress(AppContext context)
    at Microsoft.Management.Service.IntuneWinAppUtil.PackageUtil.CreatePackage(String folder, String setupFile, String outputFolder, String catalogFolder)
    at Microsoft.Management.Service.IntuneWinAppUtil.Program.Main(String[] args)
    Intunewin c:\temp\932-2311133321\\Fortinet.FortiClientVPN\installFortinet.FortiClientVPN.intunewin Created
    Test-SourceFile : Source File ‘c:\temp\932-2311133321\\Fortinet.FortiClientVPN\installFortinet.FortiClientVPN.intunewin’ doesn’t exist…
    At C:\intune\Winget_package_maker.ps1:1106 char:9
    + Test-SourceFile “$SourceFile”
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-SourceFile

    Test-SourceFile : ScriptHalted
    At C:\intune\Winget_package_maker.ps1:1106 char:9
    + Test-SourceFile “$SourceFile”
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-SourceFile

    Reply
    • Can you try loading a command prompt and type “winget list” for me? Sometimes Winget has an update which needs the licensing approving, but that blocks the script from completing.

      I would also try deleting the intunewinapputil.exe and let it download the latest version. I know there have been some issues that that app recently

      Reply
  62. Hello,

    I was wondering if there is a way to include PSADT in this tool. For Example, I want to deploy the Dell command update using this tool so I can use the proactive remediation, but I would also like for it to check for other versions of the Dell command update program and uninstall them before installing the Winget version with this PowerShell tool. I am able to do this using PSADT and the Dell command exe but was hoping to automate this using this tool .

    Thanks ,

    Reply
  63. Hello Andrew,

    thank you very much for this great Script! Unfortunatly, the Apps are detected as installed, but they are not installed. The rest of it works like a charm.. Groups are generated, the script for autoupdate is placed, but install does not work.. Do you have any idea what could be the problem?

    Reply
    • Hi,
      Is it creating and uploading the intunewin file ok?
      Does winget.exe exist here on the devices:
      C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe
      You’ll need an elevated prompt to access the folder

      Reply
      • Hey Andrew,

        thanks for the answer! The intunewim-file seems to be okay and is stored into the app settings.. I think this is the sign that the file should be okay? i will look into the logs files again, if i can find any errors..

        Yes, the winget.exe exists in the folder “C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_1.17.10691.0_x64__8wekyb3d8bbwe”

        Thank you very much for your work and this blog!

        Best regards,

        Lukas

        Reply
      • I found some other informations: Intune says that the App is installed. The detection-Script looks like this:

         $ResolveWingetPath = Resolve-Path “C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe”
        if ($ResolveWingetPath){
        $WingetPath = $ResolveWingetPath[-1].Path
        }

        $Winget = $WingetPath + “\winget.exe”
        $wingettest = &$winget list –id
        if ($wingettest -like “**”){
        Write-Host “Found it!”
        exit 0
        }
        else {
        write-host “Not Found”
        exit 1
        }

        I can say, that there is not App installed which i added with the winget-tool. If i check the installed apps with the “winget list” command, there is also no app to see.. Maybe this helps a little bit.. I tried 3 different pc’s manufactures now, i’m not able to see the problem with our usecase..

        Reply
          • Yes, that is the problem. I found the log in Windows -> Temp -> WinGet -> defaultState and that’s the output:

            2023-12-11 16:13:12.985 [CORE] WinGet, version [1.6.3133], activity [{3CB462D1-8CF6-4BF2-87F8-26999465BD16}]
            2023-12-11 16:13:12.989 [CORE] OS: Windows.Desktop v10.0.22631.2715
            2023-12-11 16:13:12.990 [CORE] Command line Args: “C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_1.21.3133.0_x64__8wekyb3d8bbwe\winget.exe” list –id
            2023-12-11 16:13:12.990 [CORE] IsCOMCall:0; Caller: winget-cli
            2023-12-11 16:13:12.992 [CLI ] WinGet invoked with arguments: ‘list’ ‘–id’
            2023-12-11 16:13:12.992 [CLI ] Found subcommand: list
            2023-12-11 16:13:12.992 [CLI ] Leaf command to execute: root:list
            2023-12-11 16:13:13.002 [CLI ] Error encountered parsing command line: Argument value required, but none found: ‘–id’

            I tried 5 different apps (webex, zoom, obs studio, teams and threema desktop) and all of these apps are throwing the error..

            I ask myself why no other person her have this problem.. Maybe there is a problem in our environment, but i reinstalled 3 notebooks and 2 fat client: same problem over all devices..

  64. Client and Tenant ID seems to be okay. The Grid-Options: “Certificate Thumbprint, Certificate SubjectName, Certificate, managedIdentityID and ClientSecret” are empty..

    Reply
  65. We changed the language to english and the problem with the id is solved! I never could imagine, that this could be a problem. Unfortunatly the installation is still not successful..
    the company portal say that the installation failed, cause the app could not be found after the installation was successful(thats not correct) or the company portal says that the installation was successful but the App is not findable..

    Thank you very much so far for your help!

    Reply
  66. Good morning,

    Currently running into an issue where the .intunewin file is not getting created.
    ERROR System.IO.IOException: The handle is invalid.

    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    at System.Console.GetBufferInfo(Boolean throwOnNoConsole, Boolean& succeeded)
    at Microsoft.Management.Service.IntuneWinAppUtil.LogUtil.PrintProgress(AppContext context)
    at Microsoft.Management.Service.IntuneWinAppUtil.PackageUtil.CreatePackage(String folder, String setupFile, String outputFolder, String catalogFolder)
    at Microsoft.Management.Service.IntuneWinAppUtil.Program.Main(String[] args)

    Above is the initial errors but I can include the whole log file.

    It is creating the Install/Uninstall/Detection Powershell scripts however.

    Reply
  67. Hi Andrew,

    Just evaluating your app deployment winget tool, and it seems that the script is getting stuck enumerating all the apps in Winget. Each time I run it, the script creates a new subfolder in C:\temp, downloads a copy of the IntuneWinAppUtil, but then just sits at the “Loading Winget Packages” progress indicator. I’ve left it running for nearly 30 minutes, without success.

    PS version: 5.1.22621.2506.
    Windows 11 23H2
    winget version 1.6.3482

    Have you seen this before?

    Reply
  68. Hi,

    I am getting the following error during app upload phase.

    Write-Error: C:\Powershell-Profile\PowerShell\Scripts\deploy-winget-win32-multiple.ps1:2717
    Line |
    2717 | … appupload = Invoke-UploadWin32Lob -SourceFile “$appfile” -DisplayName …
    | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    | Aborting with exception: System.Management.Automation.ParameterBindingValidationException: Cannot bind argument
    | to parameter ‘Exception’ because it is null. at
    | System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception
    | exception) at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
    | at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) at
    | System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
    0

    Have you seen this error before?

    Reply
  69. Hi Andrew! I hope everything is going well. I have deployed several applications and Remediations using this script. I have users complain that a cmd prompt is displayed several times daily. After further review, I believe it happens when the remediation scripts run. Is there a way to disable that, or did I deploy the remediations incorrectly?

    For example:
    -Added Canva application and remediation using the PowerShell script
    -I have assigned the remediation to all Devices
    -The remediation is set to check every hour for this application
    -User opens the application, and cmd pops up and stays up for about a minute, then closes
    -Any help or suggestions would be greatly appreciated.

    Reply
  70. Hi Andrew,

    Thanks for the great content. Just trying the script and when I run it gives me this error below from the logging. I’m guessing the script cannot create the intunewin file because it doesn’t accept the same path “$apppath” as both destination and source path, then because of this this goes on and cannot find source file down below and errors out. Can you help?
    Here is the log file:

    Success
    Proactive Remediation Created and Assigned for 7-Zip
    VERBOSE: Creating Intunewin File for 7-Zip
    VERBOSE: Begin creating package
    New-IntuneWinPackage : DestinationPath can’t be a subfolder of SourcePath
    At C:\Program Files\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:2461 char:5
    + New-IntuneWinPackage -SourcePath “$apppath” -SetupFile “$setupfil …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [New-IntuneWinPackage], Exception
    + FullyQualifiedErrorId : 1,SvR.ContentPrep.Cmdlet.NewIntuneWinPackageCommand
    New-IntuneWinPackage : DestinationPath can’t be a subfolder of SourcePath
    At C:\Program Files\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:2461 char:5
    + New-IntuneWinPackage -SourcePath “$apppath” -SetupFile “$setupfil …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [New-IntuneWinPackage], Exception
    + FullyQualifiedErrorId : 1,SvR.ContentPrep.Cmdlet.NewIntuneWinPackageCommand

    Intunewin c:\temp\521-2403050429\\7zip.7zip\install7zip.7zip.intunewin Created
    VERBOSE: Uploading 7-Zip to Intune
    VERBOSE: Testing if SourceFile ‘c:\temp\521-2403050429\\7zip.7zip\install7zip.7zip.intunewin’ Path is valid…
    Test-SourceFile : Source File ‘c:\temp\521-2403050429\\7zip.7zip\install7zip.7zip.intunewin’ doesn’t exist…
    At C:\Program Files\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:1101 char:9
    + Test-SourceFile “$SourceFile”
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-SourceFile
    Test-SourceFile : Source File ‘c:\temp\521-2403050429\\7zip.7zip\install7zip.7zip.intunewin’ doesn’t exist…
    At C:\Program Files\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:1101 char:9
    + Test-SourceFile “$SourceFile”
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-SourceFile

    Test-SourceFile : ScriptHalted
    At C:\Program Files\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:1101 char:9
    + Test-SourceFile “$SourceFile”
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-SourceFile
    Test-SourceFile : ScriptHalted
    At C:\Program Files\WindowsPowerShell\Scripts\deploy-winget-win32-multiple.ps1:1101 char:9
    + Test-SourceFile “$SourceFile”
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-SourceFile

    PS>TerminatingError(): “System error.”
    >> TerminatingError(): “System error.”
    >> TerminatingError(): “System error.”

    Reply
  71. I have a similar problem to a colleague above. For me the AppID remains empty. An example with the first software in the list “Compass”. In the NAME column it says compass zype.compass. The ID field is empty. In the VERSION field is the version number, MOnker:winget. the remaining columns are empty again. Something seems to be going wrong during parsing. Any idea?

    Reply
  72. Maybe something to do with the file encoding? If I open it with notepad++ using utf 8 it looks like this:
    if ($PSBoundParameters.ContainsKey(‘Filter’)) {
    ## Search across Name, ID, moniker, and tags
    $WinGetArgs += $Filter
    }
    if ($PSBoundParameters.ContainsKey(‘Id’)) {
    ## Search for the ID
    $WinGetArgs += “–Id”, $Id.Replace(“…”, “”)
    }
    if ($PSBoundParameters.ContainsKey(‘Name’)) {
    ## Search for the Name
    $WinGetArgs += “–Name”, $Name.Replace(“…”, “”)
    }
    if ($PSBoundParameters.ContainsKey(‘Moniker’)) {
    ## Search for the Moniker
    $WinGetArgs += “–Moniker”, $Moniker.Replace(“…”, “”)
    }
    if ($PSBoundParameters.ContainsKey(‘Tag’)) {
    ## Search for the Tag
    $WinGetArgs += “–Tag”, $Tag.Replace(“…”, “”)

    Reply

Leave a Comment