Visual Studio 2022 Community/C++: My Pre-Build PowerShell script runs successfully, but the end result is not achieved.

ondafringe 10 Reputation points
2024-07-05T18:53:26.38+00:00

I trade the market using Sierra Chart (SC) software. I use VS to create a DLL and need to build and deploy the updated DLL to an SC folder without having to shutdown SC in order to release the DLL for writing/updating.

I created a PowerShell (PS) script that uses the UDP port in SC to send a release-DLL directive to SC. When I run that script from the pre-build event within VS, the script runs without error, but SC does not release the DLL, so VS cannot open the DLL for writing.

My PS execution policy is set to: RemoteSigned CurrentUser and AllSigned LocalMachine

======================

This was in my Pre-Build Event

PowerShell "Start-Process PowerShell.exe"
PowerShell .\ReleaseDLL.ps1

======================

However, when I manually open a PS window and manually run the same release-DLL script from there, it works as expected -- SC releases the DLL, and VS can successfully deploy the updated DLL. I don't have to open the PS window as Admin, either.

I have a work-around solution where, In the pre-build event, I open a PS window, simulate Ctrl-v to paste the file name into PS, and then simulate pressing the main Enter key to run the script. Then, in the post-build event, I just reverse the process, using a reload-DLL script, and then close the PS window. That works, but it seems like more than should be required.

Any suggestion as to how I can get that script to work when run from the pre-build event?

Thank you.

Visual Studio
Visual Studio
A family of Microsoft suites of integrated development tools for building applications for Windows, the web and mobile devices.
4,888 questions
{count} votes

3 answers

Sort by: Most helpful
  1. ondafringe 10 Reputation points
    2024-07-07T00:47:06.9066667+00:00

    To the moderators: I think I posted this to the wrong place, with the wrong tag.

    I have since reposted the question with a "Visual Studio" tag. So feel free to delete this question, if you so desire.

    1 person found this answer helpful.

  2. ondafringe 10 Reputation points
    2024-07-07T18:05:12.5+00:00

    @mikelydick

    The script you provided helped out a great deal, and I got an error indicating it was a permission problem.

    https://learn.microsoft.com/en-us/visualstudio/msbuild/errors/msb3075?view=vs-2022&devlangs=cpp&f1url=%3FappId%3DDev17IDEF1%26l%3DEN-US%26k%3Dk(MSBuild.Exec.CommandFailedAccessDenied)%3Bk(DevLang-C%252B%252B)%26rd%3Dtrue

    It turns out, VS needs to have permission to run PS scripts. After digging around, I found out I needed to add a PowerShell extension to VS, which I did:

    VS>Extensions>PowerShell Tools for Visual Studio 2022

    I also updated my .Net components, and used what you suggested in my Pre-/Post-Build Events:

    powershell.exe -ExecutionPolicy Bypass -File "$(ProjectDir)ReleaseDLL.ps1"

    powershell.exe -ExecutionPolicy Bypass -File "$(ProjectDir)ReloadDLL.ps1"

    Once I did all that, everything seems to be working as expected. Thank you, I appreciate your help!

    1 person found this answer helpful.

  3. mikelydick 76 Reputation points
    2024-07-07T00:59:26.7266667+00:00

    I understand your situation. You're trying to automate the process of releasing a DLL from Sierra Chart (SC) before building and deploying it from Visual Studio (VS), without having to shut down SC. Let's analyze the problem and explore some potential solutions.

    
    # ReleaseDLL.ps1
    
    # Function to send UDP message to Sierra Chart
    
    function Send-UDPMessage {
    
        param (
    
            [string]$Message,
    
            [string]$IPAddress = "127.0.0.1",
    
            [int]$Port = 19700  # Adjust this port number if necessary
    
        )
    
        $EndPoint = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Parse($IPAddress), $Port)
    
        $UDPClient = New-Object System.Net.Sockets.UdPClient
    
        try {
    
            $EncodedMessage = [System.Text.Encoding]::ASCII.GetBytes($Message)
    
            $UDPClient.Send($EncodedMessage, $EncodedMessage.Length, $EndPoint)
    
        }
    
        finally {
    
            $UDPClient.Close()
    
        }
    
    }
    
    # Send release DLL command to Sierra Chart
    
    Send-UDPMessage -Message "ReleaseDLL"
    
    # Wait for Sierra Chart to process the command
    
    Start-Sleep -Seconds 2
    
    # Check if the DLL is now writable
    
    $dllPath = "C:\Path\To\Your\DLL.dll"  # Update this path
    
    $attempts = 0
    
    $maxAttempts = 5
    
    while ($attempts -lt $maxAttempts) {
    
        try {
    
            $fileStream = [System.IO.File]::Open($dllPath, 'Open', 'Write')
    
            $fileStream.Close()
    
            Write-Output "DLL successfully released and is now writable."
    
            exit 0
    
        }
    
        catch {
    
            $attempts++
    
            if ($attempts -ge $maxAttempts) {
    
                Write-Error "Failed to release DLL after $maxAttempts attempts."
    
                exit 1
    
            }
    
            Start-Sleep -Seconds 1
    
        }
    
    }
    
    

    Now, let's break down the problem and propose a solution:

    1. Script Execution Environment: When you run the script manually from a PowerShell window, it works, but not when executed from the VS pre-build event. This suggests that the execution environment or permissions might be different.
    2. UDP Communication: The script uses UDP to communicate with Sierra Chart. Ensure that the UDP port (usually 19700) is correctly set and not blocked by a firewall.
    3. Timing Issues: There might be a race condition where VS tries to access the DLL before Sierra Chart has fully released it.
    4. Error Handling and Logging: The current script might not provide enough information about what's happening during execution.

    Here's what I suggest:

    1. Use the improved script in the artifact above. This script:
      • Includes error handling and logging.
      • Implements a retry mechanism to ensure the DLL is actually released before proceeding.
      • Uses a function to send the UDP message, making it easier to debug and maintain.
    2. In your VS pre-build event, use this command instead:
    
    powershell.exe -ExecutionPolicy Bypass -File "$(ProjectDir)ReleaseDLL.ps1"
    
    

    This ensures that the script runs with the necessary permissions and in the correct working directory.

    1. If the issue persists, add more logging to the script to understand what's happening. You can write logs to a file for later inspection.
    2. Check if there are any differences in environment variables or system state between your manual PowerShell execution and the VS-triggered execution. You might need to set specific environment variables in the pre-build event.
    3. Ensure that VS is running with the necessary permissions to interact with Sierra Chart and modify the DLL.
    4. If timing is still an issue, you might need to increase the wait time in the script or implement a more robust check to ensure Sierra Chart has fully released the DLL.

    If you implement these changes and still face issues, we can further debug by adding more detailed logging to the script and analyzing the output. Let me know if you need any clarification or have any questions about implementing these suggestions.