6

I have a small PowerShell script wrapped in an exe (using Quest Power GUI). This exe is then deployed to a UNC path using mageUI.exe (i.e. through a 'ClickOnce' deployment).

Now, there is a namespace available to us:

System.Deployment.Application

This namespace allows us to figure out if the tool is network deployed + the originating download URL/UNC of the exe.

So I added the following lines in my PowerShell script (which was then compiled into an exe by PowerGUI)

# Line 1. Load the assembly
[System.Reflection.Assembly]::LoadWithPartialName("System.Deployment")

# Line 2. Utilise methods in the assembly. Below line will give either false or true, depending if the caller is deployed as a 'ClickOnce' app.
[System.Deployment.Application.ApplicationDeployment]::IsNetworkDeployed

After publishing this exe as a 'ClickOnce' application (using mageUI.exe), putting it on a network share, and then executing from some other server (which has access to previously said share), I still get the following output:

# Output of Line 1 (This signifies the assembly was loaded successfully)
GAC    Version        Location
---    -------        --------
True   v4.0.30319     C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Deployment\v...

# Output of Line 2
False

Not sure what I'm doing wrong. The property IsNetworkDeployed (Line 2) should have returned true.

Vish
  • 466
  • 2
  • 12
  • 1
    What did you put on the network share, the clickonce deployment, or the actual files that were being installed? I ask because as far as I know, clickonce always installs the files locally, so perhaps it *installed* it from the network share, but installed them locally? – Lasse V. Karlsen Nov 27 '20 at 15:59
  • So the network share contains the all the deployment file as per this [article](https://learn.microsoft.com/en-us/visualstudio/deployment/walkthrough-manually-deploying-a-clickonce-application?view=vs-2019). Basically the manifest file and the actual EXE in a sub-folder by the name of `1.0.0.0`, and the `.application` file in the root shared folder. – Vish Nov 27 '20 at 17:11
  • Yes -- The application was installed locally. Would that impose a problem? In my scenario the application does need to get installed locally, but the app itself still needs to figure out it's own originating URL. – Vish Nov 27 '20 at 17:18
  • No, never mind me, I am right and you're right but I'm talking about something else. – Lasse V. Karlsen Nov 27 '20 at 17:25
  • How do you execute it? Just double click? The `Location` indeed suggests a local drive: `C:\...`. Do you have something like offline-files enabled? What happens when you force to start the file from the share, like: `\\Server\share\Your.exe` ? – iRon Dec 01 '20 at 11:36
  • @Vish did you enable clickonce security settings in your application properties ? – NajiMakhoul Dec 01 '20 at 11:50
  • @NajiMakhoul Are you talking about the parameters to be selected when creating a `deploy manifest`?. `Pass Parameters from URL` and `Enable Provider URL Location` are both selected. – Vish Dec 01 '20 at 12:24
  • @iRon : Currently, the EXE gets executed by passing the shared path in the `run` prompt. Mind you, this actually invokes the `.application` file from the shared path and executes it as an exe successfully. But the `isnetworkdeployed` property still gives false. – Vish Dec 01 '20 at 12:27
  • 1
    UPDATE: Think I figured out the issue... Quest PowerGUI pretty much "extracts" the exe into a temp folder, and then executes it. This would always cause the extracted script to technically never be deployed from a network (since the exe is network deployed, but the extracted script isn't). I tested this out with PS2EXE, which executes "in-memory", which then successfully returns true. Can anyone confirm if my assumption is really the case? +50 if you can prove me correct/wrong (and of course could quote correct sources/materials). – Vish Dec 01 '20 at 12:33

2 Answers2

0

Seeing that there is no solution using PowerGUI (since the script is extracted into a temp folder during execution), I had to do the following:

 1. Create a 'caller' / 'wrapper' executable using [PS2EXE](https://gallery.technet.microsoft.com/scriptcenter/PS2EXE-Convert-PowerShell-9e4e07f1)
 2. This executable becomes the 'entry point' while deploying as a clickOnce application.
 3. Since the 'wrapper' is executed 'in-memory', the deployment methods/properties from System.Deployment work (if it's deployed through clickOnce).
 4. There is some logic written in the wrapper exe which calls the second (which contains the actual working) executable. Ex:

IF ISNETWORKDEPLOYED, THEN:
    PARSE THE URL ARGS / PREPARE THE ARGS AND PASS IT TO THE SECOND EXECUTABLE (which was compiled using Quest PowerGUI previously)

I am open to any other solutions.

Vish
  • 466
  • 2
  • 12
0

As it appears that the concerned script does actually runs locally (as suggested), which appears to be caused by the exe wrapping, Instead, you might want to browse (C:, CD \Path) to your exe location and use the current location:

(get-location).Path

General Note
I would reconsider the overall design knowing that this wrapper is probably (mis)used to cover sensitive information (as hardcoded passwords), called Security through obscurity. If that is indeed the case, a (legal) hacker will easily shoot a hole into this. There several ways to deal with sensitive information in scripts by e.g. limiting the shared credentials and/or using the credentials of the current user instead.

iRon
  • 20,463
  • 10
  • 53
  • 79
  • I have updated my answer as you might be able to workaround this by using the current location `(get-location).Path` instead. – iRon Feb 11 '21 at 11:22