OpenCDSS / cdss-app-statecu-fortran

Colorado's Decision Support Systems (CDSS) StateCU consumptive use model code, documentation, tests
GNU General Public License v3.0
1 stars 1 forks source link

Add a StateCU run script to provide generic run command #32

Open smalers opened 3 years ago

smalers commented 3 years ago

LATEST UPDATE - I successfully created a statecu.cmd file to generically run StateCU without need for PowerShell. This discussion is still relevant in the bigger picture but does not urgently need a response from the State.

I am trying to release the StateCU executable in a way that is robust and does not burden users with technical issues.

I am going to continue with a PowerShell approach (Option 1 discussed below) but need the State people to weigh in on whether there are issues in their environment when allowing PowerShell to be used as I've described.

Background

Recent work on the development environment and updating to the latest gfortran compiler has resulted in executable file names that are verbose, such as the following. This is actually more of an issue for StateMod, which is being handled similarly, because StateMod is moving from 32bit to 64bit, from Lahey go gfortran compilers, and version numbers when omitted, have caused confusion. Basically, we need to be more verbose to avoid confusion and in the future maybe the parts can be removed. Detailed version numbers can also help cross-reference to documentation release nots.

statecu-14.0.0-gfortran-win-64bit.exe

For modeling, the StateCU folder (or StateMod for StateMod) in datasets contains the input files for a model run. To ensure that the correct software is used, one approach is to copy the executable into that folder and distribute with the dataset. However, using long versioned executable names is cumbersome for users and poses some challenges to tools that want to run the model using a generic name. Renaming the long names to short/generic names poses the problem that a user no longer knows the version number that they are running. They could run the -version option but there could still be confusion. And, if you want to try multiple versions, you have to put a version on anyhow so might as well use the verbose names to begin with.

Attempted Solution trying Windows Batch File

One way to solve this problem is to distribute a generic name. The generic program will determine the executable name to run and can default to using the latest version if there happens to be more than one executable in the folder. It is conceivable that a person with enough skill could try running different versions.

There is precedent for this. The Python software is distributed with py program that figures out which version of Python is installed an can be run. I have also used this approach to run different versions of QGIS.

My initial approach for Windows was to write a statecu.cmd script. However, the limited functionality of cmd scripts is causing issues. In particular, I need a way to list the executables in alphabetical order and then pick the most recent. This is equivalent to the head or tail linux command. Advice on the web repeatedly points to using a PowerShell script. Actually, using PowerShell rather than bat or cmd would provide great additional functionality for CDSS tools.

Proposed Solution using PowerShell

So... I'm going to try to lay out a PowerShell solution. To provide a preview, this could involve a couple of approaches:

  1. Implement a solution using only a PowerShell script such as statecu.ps1 (the ps1 file extension is used for PowerShell version 1 scripts).
  2. Implement a solution where statecu.cmd calls statecu.ps1. This seems like overkill but read on for why this may be needed if statecu.cmd can't integrate well enough with PowerShell in one script.

In any case, PowerShell needs to be available and enabled.

Is PowerShell Enabled?

Much literature on the web says to "Just move to PowerShell!" rather than continuing to create old-style Windows batch files. A basic question, however, is whether PowerShell is available to users that are expected to try running CDSS models in the way that is discussed above. To evaluate, try running the following from a Windows command shell:

powershell
PS .... > $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.19041.1151
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.19041.1151
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

It is likely that powershell is installed in some form because Windows uses it to do administrator work.

However, for average users, PowerShell is restricted. The following shows some experiments I did trying to get a list of files in a folder. In this case I called powershell from a cmd file.

@rem Test running a powershell script.

@rem If the following is run, it shows:
@rem     C:\Users\sam\cdss-dev\StateCU\git-repos\cdss-app-statecu-fortran-test\test\datasets\cm2015_StateCU\exes\statecu-14.0.0-gfortran-win-64bit\StateCU\statecu.ps1 : File
@rem     C:\Users\sam\cdss-dev\StateCU\git-repos\cdss-app-statecu-fortran-test\test\datasets\cm2015_StateCU\exes\statecu-14.0.0-gfortran-win-64bit\StateCU\statecu.ps1 cannot be loaded because running scripts is disabled on this
@rem     system. For more information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.
@rem     At line:1 char:1
@rem     + C:\Users\sam\cdss-dev\StateCU\git-repos\cdss-app-statecu-fortran-test ...
@rem     + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@rem         + CategoryInfo          : SecurityError: (:) [], PSSecurityException
@rem         + FullyQualifiedErrorId : UnauthorizedAccess

@rem statecu.ps1

@rem Try running the following to temporarily allow.
@rem Note that the account being used DOES NOT have admin privileges.
@rem The following does not work because 'powershell' tries to run 'statecu.ps1 as a command.
@rem    statecu.ps1 : The term 'statecu.ps1' 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
@rem    try again.
@rem    At line:1 char:1
@rem    + statecu.ps1
@rem    + ~~~~~~~~~~~
@rem    + CategoryInfo          : ObjectNotFound: (statecu.ps1:String) [], CommandNotFoundException
@rem    + FullyQualifiedErrorId : CommandNotFoundException

@rem powershell -ExecutionPolicy Unrestricted statecu.ps1

@rem The following works because 'powershell' finds the 'statecu.ps1' file in the current folder.
@rem Apparently it is somewhat like Linux and its use of 'PATH'.
powershell -ExecutionPolicy Unrestricted .\statecu.ps1

The above shows that it is possible to run a powershell script as a desktop user by temporarily changing the execution policy. Given that I ran this as a non-administrator user, I assume that if I tried to do anything serious that I'd be prompted for credentials. The problem is that I want a simple solution to change the execution policy so that a user does not have to type that.

In Linux, the #! syntax on the first line of a script can be used to tell the operating system how to run the script, for example, something like:

#! powershell -ExecutionPolicy Unrestricted

However, this does not help in a pure Windows environment because no linux shell is available. If there were an equivalent way to provide the information so that statecu.ps1 can be run in unrestricted mode?

Option 0

Figure out what I need to get working in Windows command shell. This has been a challenge but if I happen to do the correct search, maybe I can figure it out. I'm going to at least try Option 1.

Option 1

The work-around is to use a statecu.cmd script that calls powershell, as in the working example above. This means that StateCU long excutable name, statecu.cmd, and statecu.ps1 would be distributed with a dataset. Most users would only ever run statecu.cmd (e.g., by typing statecu cm2015).

Option 2

Alternatively, I could try to put all the logic in statecu.cmd and call powershell where useful. The downside is that this still uses old commands, which are limited in functionality, and harder to develop and maintain. Given limited time and because I have a mostly-working statecu.cmd I am probably going to go this route. Only statecu.cmd would be distributed.

Option 3

A better solution would be a statecu.ps1 that runs in unrestricted mode and therefore would distribute statecu.ps1.

Option 3 is do all the coding in PowerShell but call from a cmd file to run as unrestricted. The downside is this would require distributing statecu.cmd and statecu.ps1. I also tried running in PowerShell directly (see below) but this did not work out cleanly.

Associating ps1 Extension with PowerShell

In order for use of PowerShell to be easier, users may need to associate the ps1 extension with PowerShell, for example:

https://www.top-password.com/blog/set-ps1-script-to-open-with-powershell-by-default/

Given that most modelers should have a bit of technical know-how, it seems that doing the above should be OK.

This may only be required if the file is used in certain ways such as typing statecu on the command line to run statecu.ps1. However, my test indicates that trying to do this from a Windows command shell does not run the powershell script even if the file extension is properly associated.

If I open a PowerShell application window, I do get a PowerShell session and prompt. I had to type .\statecu.ps1 to get it to run, but it gives me the error about being disabled. It would be really great to open a PowerShell (instead of Windows command shell) and run statecu (to run statecu.ps1). These are things the average user could do.

I am going go focus on a solution without PowerShell.

smalers commented 3 years ago

I successfully created a statecu.cmd script that does what is needed. I'll keep this issue open in case the State wants to comment on PowerShell but it can be closed if no action occurs in a few weeks.

macphersonbr commented 3 years ago

I was able to successfully run:

powershell
PS .... > $PSVersionTable

but I have administrator privileges on my machine that others may not have.