locked
Connecting to EXOPSSession via Visual Basic Console Application RRS feed

  • Question

  • I successfully execute the following commands from the Windows PowerShell ISE on a 2008 R2 server.

    Set-ExecutionPolicy RemoteSigned
    $pw = convertto-securestring -AsPlainText -Force -String "Password"
    $cred = New-Object -typename System.Management.Automation.PSCredential -argumentlist "Login", $pw
    $Session = New-EXOPSSession -ConnectionUri 'https://ps.compliance.protection.outlook.com/powershell-liveid' -Credential $cred
    Import-PSSession $Session -AllowClobber -DisableNameChecking

    However, when I execute these same commands on the same server from a .Net Console Application I receive the following error.

    System.Management.Automation.CommandNotFoundException: The term 'New-EXOPSSession' 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 System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input) at System.Management.Automation.Runspaces.Pipeline.Invoke() at My.Module1.RunScript(String scriptText, String& ReturnCode)

    Thanks,

    Don

    Tuesday, July 30, 2019 4:07 PM

Answers

  • Adding a reference to the module directly into my app resolved my problem.

    Thank you all for your help!

    Tuesday, July 30, 2019 8:31 PM

All replies

  • You probably need to import the module that contains the 'New-EXOPSSession' into your runspace.

    when you create a new PowerShell instance in code, it doesn't run any profile scripts like the powershell.exe application does, so many of the features you are used to in PowerShell.exe are not loaded.  

    I often do this:

    var _ps = System.Management.Automation.PowerShell.Create();
    _ps.AddScript("import-module TheModuleNameToImport");
    _ps.Invoke();
    // check for errors
    if (_ps.Streams.Error.Count) { throw _ps.Streams.Error[0].Exception; }
    
    // clear the last stuff so we can use .AddScript again.
    _ps.Commands.Clear();
    
    




    -Eriq VanBibber, CTO, Priasoft Inc.

    • Proposed as answer by jrv Tuesday, July 30, 2019 4:23 PM
    Tuesday, July 30, 2019 4:19 PM
  • I added the following statement as the first line of my script.

    Import-Module -Name 'Microsoft.Exchange.Management.ExoPowershellModule.dll'

    Now I receive the following error message:

    System.IO.FileNotFoundException: The specified module 'Microsoft.Exchange.Management.ExoPowershellModule.dll' was not loaded because no valid module file was found in any module directory. 

    I have confirmed this file exists in the following folder: 

    C:\Program Files\WindowsPowerShell\Modules\Microsoft.Exchange.Management.ExoPowershellModule\16.0.0.0


    Tuesday, July 30, 2019 5:54 PM
  • Well, i don't think the 'name' parameter is supposed to be used for filenames.  instead, the -name parameter is for the module name, which references and properly install module. 

    you can get all installed modules with:  Get-Module -ListAvailable.
    This will output the modules names as well as other detail.

    For loading a DLL, i think you have to use -Assembly to point to a compiled module.

    Let me know if this info is clearly written and relevant.



    -Eriq VanBibber, CTO, Priasoft Inc.

    Tuesday, July 30, 2019 6:02 PM
  • Import-Module Microsoft.Exchange.Management.ExoPowershell

    If it is a full  module just use the module name.  Be sure the folder is in the "$env:PsModuklePath" environment variable.  If it auto-imports in IE then the path should be correct.


    \_(ツ)_/

    Tuesday, July 30, 2019 6:03 PM
  • "-Assembly" is not a parameter of Import-Module. It is only available on "Add-Type". Modules must be imported using the module name or the full path to the base module.

    Import-Module -FullyQualifiedName <path to module base psd1 or dll file.

    It is best to only use the module name in compiled code as the module can be installed in different locations on different systems.  The module path variable is intended to allow loading from any known module location.


    \_(ツ)_/


    • Edited by jrv Tuesday, July 30, 2019 6:09 PM
    Tuesday, July 30, 2019 6:07 PM
  • Maybe that is a version specific thing then for you.

    -Assembly is clearly there for the cmdlet.

    i have the following powershell instance:

    Name             : ConsoleHost
    Version          : 5.1.18362.145
    InstanceId       : eff8625b-c342-4941-a95f-4e21690c607d
    UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
    CurrentCulture   : en-US
    CurrentUICulture : en-US
    PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
    DebuggerEnabled  : True
    IsRunspacePushed : False
    Runspace         : System.Management.Automation.Runspaces.LocalRunspace


    -Eriq VanBibber, CTO, Priasoft Inc.

    Tuesday, July 30, 2019 6:12 PM
  • Ok but it doesn't auto-complete in PowerShell CLI on Win10 and it requires a "System.Reflection.Assembly" reference and not a name or path.

    It is used mostly to select subsets of a module assuming you have a reference to the assembly.

    The OP has a module in the correct path so only the name is required and it is the preferred and most portable method.


    \_(ツ)_/

    Tuesday, July 30, 2019 6:20 PM
  • Also be aware that we don't use "Set-ExecutionPolicy RemoteSigned" in a script.  It can only be run by an elevated admin and will throw errors if used in a compiled program executing a script.

    The systems should be set up before any scripts are run.  In a domain this is done via Group Policy.


    \_(ツ)_/

    Tuesday, July 30, 2019 6:23 PM
  • I have tried importing the module 4 different ways:

    Import-Module 'Microsoft.Exchange.Management.ExoPowershell'

    Import-Module 'Microsoft.Exchange.Management.ExoPowershell.dll'

    Import-Module 'C:\Program Files\WindowsPowerShell\Modules\Microsoft.Exchange.Management.ExoPowershellModule\16.0.0.0\Microsoft.Exchange.Management.ExoPowershell.dll'

    Import-Module 'C:\Program Files\WindowsPowerShell\Modules\Microsoft.Exchange.Management.ExoPowershellModule\16.0.0.0\Microsoft.Exchange.Management.ExoPowershell'

    Each attempt resulted in the same error: Module was not loaded because no valid module file was found in any module directory.

    Interestingly when I run "Get-Module -ListAvailable" from ISE I do not see the Microsoft.Exchange.Management.ExoPowershell module listed, yet these commands run perfectly fine from ISE.

    Tuesday, July 30, 2019 6:32 PM
  • That is likely because the module is not in the path.

    Output the path for the account you are running under.

    You can also do this:

    $dll = Get-Item 'C:\Program Files\WindowsPowerShell\Modules\Microsoft.Exchange.Management.ExoPowershellModule\16.0.0.0\Microsoft.Exchange.Management.ExoPowershell.dll'
    Write-Host $dll.Fullname


    \_(ツ)_/

    Tuesday, July 30, 2019 6:55 PM
  • The other big issue can be 32 v 64 bit environments.


    \_(ツ)_/

    Tuesday, July 30, 2019 6:56 PM
  • You can check you module paths like this:

    $env:PsModulePath -split ';' | Write-Host

    Be sure the module path you are looking for is listed.


    \_(ツ)_/

    Tuesday, July 30, 2019 6:59 PM
  • Results of Get-Item command:

    Get-Item : Cannot find path 'C:\Program Files\WindowsPowerShell\Modules\Microsoft.Exchange.Management.ExoPowershellModule\16.0.0.0\Microsoft.Exchange.Management.ExoPowershell.dll' 
    because it does not exist.
    At line:1 char:8
    + $dll = Get-Item 'C:\Program Files\WindowsPowerShell\Modules\Microsoft ...
    +        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : ObjectNotFound: (C:\Program File...oPowershell.dll:String) [Get-Item], ItemNotFoundException
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand

    I installed the module from ISE with command:

                            Install-Module -Name Microsoft.Exchange.Management.ExoPowershellModule 

    Print screen of Exo folder.


    Tuesday, July 30, 2019 7:05 PM
  • That usually means that your program hasn't been given access to the file system. Remember CAS. I recommend posting in the VB.Net forum to learn how to set up your code to access the files system. How it is done depends on the type of program you are writing.

    Don't feel bad. This happens to all newcomers to programming in Windows.  Understanding Visual Studio and how to configure a programs settings takes a good bit of time to learn.

     


    \_(ツ)_/

    Tuesday, July 30, 2019 7:13 PM
  • Results of $env:PsModulePath -split ';' | Write-Host

    C:\Program Files\WindowsPowerShell\Modules
    C:\Windows\system32\WindowsPowerShell\v1.0\Modules\

    When executing Get-Module -ListAvailable, the Exo module is found in the first directory.


        Directory: C:\Program Files\WindowsPowerShell\Modules

    ModuleType Version    Name                                ExportedCommands                                                              --------- -------    ----                                ----------------                                                                            Manifest   16.0.0.0   Microsoft.Exchange.Management.Ex... New-ExoPSSession 

    Tuesday, July 30, 2019 7:13 PM
  • My best guess is that you compiled your program as a 32 bit program. This will give you the path but the modules will not be there because they are in the 64 bit view of the system.


    \_(ツ)_/

    Tuesday, July 30, 2019 7:18 PM
  • The account I am authenticated to the server with has local admin rights.  This is the same account I am executing the Windows console app under.  I have also tried "run as administrator" to make sure it is running with elevated rights.
    Tuesday, July 30, 2019 7:19 PM
  • The account I am authenticated to the server with has local admin rights.  This is the same account I am executing the Windows console app under.  I have also tried "run as administrator" to make sure it is running with elevated rights.

    Is your app being compiled as a 32 bit app?


    \_(ツ)_/

    Tuesday, July 30, 2019 7:23 PM
  • well, i think you cannot import the reference because it's technically not a "module".

    refer to this for understanding: https://stackoverflow.com/questions/10766334/how-to-find-the-target-exe-file-of-appref-ms

    The windows shortcut for this is a special type of installer reference that basically "dynamically" installs the module for the current powershell instance.

    as such, i don't think this can be automated.

    you may have to revert to the traditional New-PSSession/Import-PSSession calls for Exchange powershell.  You'll lose the 2-factor support, but such can be at least automated.

    The following is the windows shortcut for the powershell module.


    -Eriq VanBibber, CTO, Priasoft Inc.


    • Edited by Eriq VanBibber Tuesday, July 30, 2019 7:38 PM added clickable link
    Tuesday, July 30, 2019 7:31 PM
  • So explain how ISE is able to import the module?


    \_(ツ)_/

    Tuesday, July 30, 2019 7:35 PM
  • The target CPU for my app was "Any".  I changed it to x64 and recompiled.  Same result.

    As an FYI, I have been executing PowerShell scripts successfully from this same console app against AzureAD without any issue.  The AzureAD module is located under the same modules folder as Exo:  


    Tuesday, July 30, 2019 7:36 PM
  • Just executed the following commands from the console app to confirm access to the folder.

    string [] fileEntries = Directory.GetFiles("C:\Program Files\WindowsPowerShell\Modules\Microsoft.Exchange.Management.ExoPowershellModule\16.0.0.0"); foreach(string fileName in fileEntries) console.writeline(fileName);

    A complete file listing of the folder was output.

    Tuesday, July 30, 2019 8:06 PM
  • Then you are up against what Eriq noted earlier. The code cannot be loaded as a module or an assembly. It must be installed into the app.


    \_(ツ)_/

    Tuesday, July 30, 2019 8:08 PM
  • It looks like someone else may have figure something out in relation to this.

    https://blogs.technet.microsoft.com/richardroddy/2018/04/04/using-powershell-ise-to-connect-to-exchange-online-when-mfa-is-enabled/

    Basically, they found the underlying *.ps1 script file that makes this all work and they invoke that script manually.

    however, i would offer some caution on this given then dynamic nature of this.  if Microsoft decides to change some of how this works, the script file mentioned above could be out of date and cause a failure later.

    nonetheless, if the above works, my previous comment about using _ps.AddScript() could work. You'd simply load the entire text of that file into that method as a string, then call _ps.Invoke().

    I'm not sure that _ps.AddScript(".\scriptfile.ps1") will work however.  you'd have to experiment with this.


    -Eriq VanBibber, CTO, Priasoft Inc.

    • Proposed as answer by jrv Tuesday, July 30, 2019 8:25 PM
    • Unproposed as answer by jrv Wednesday, July 31, 2019 6:38 AM
    Tuesday, July 30, 2019 8:18 PM
  • Adding a reference to the module directly into my app resolved my problem.

    Thank you all for your help!

    Tuesday, July 30, 2019 8:31 PM
  • Adding a reference to the module directly into my app resolved my problem.

    Thank you all for your help!

    Funny. I was going to suggest that but, with no way to test it, I decided not to post it.

    Good.  Now we know how the DLL is build and that it is designed as a usable assembly directly in code.


    \_(ツ)_/

    Tuesday, July 30, 2019 8:34 PM
  • Hi,

    Was your issue resolved?

    If you resolved it using our solution, please "mark it as answer" to help other community members find the helpful reply quickly.

    If you resolve it using your own solution, please share your experience and solution here. It will be very beneficial for other community members who have similar questions.

    If no, please reply and tell us the current situation in order to provide further help.

    Best Regards,

    Lee


    Just do it.

    Wednesday, July 31, 2019 6:17 AM