1. Hey! Guest! The 33rd GMC Jam will take place between May 23rd, 12:00 UTC (Friday noon) and May 27th, 12:00 UTC (Monday noon). Why not join in! Click here to find out more!
    Dismiss Notice

Asset - Extension Execute Shell (for Windows, macOS, and Ubuntu)

Discussion in 'Marketplace' started by Samuel Venable, Sep 13, 2016.

  1. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    [​IMG]

    [​IMG]

    [​IMG]

    This extension is for Windows, macOS and Ubuntu.

    Execute third-party applications from your GameMaker Studio games.

    Open or run any file type, whether EXE or not. Supports "wait" param.

    The DLL's full source code included.

    Very big thanks to Josh Ventura, for writing the widen() and shorten() scripts, enabling UTF-8 support on Windows.

    Download Free for GameMaker Studio 1.4 and 2
     
    Last edited: Oct 5, 2018
    EvanSki, Stoozey, Tthecreator and 4 others like this.
  2. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    This extension has had over 600 downloads, so I assume a good number of users here have it. Is anyone ok with showing me your project and how it uses my extension? I'm just a little curious as to what it is being used for.
     
  3. RizbIT

    RizbIT Member

    Joined:
    Jun 24, 2016
    Posts:
    401
    I had a similar one that kept crashing at game start. Is this one stable and work every time game starts?
     
  4. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    Hi @RizbIT

    If you set the wait parameter to 1 on Windows and try to click on or mess with the main game window while waiting for the process to close, it will crash. This is a bug with GM:S itself and how it handles non-async dll calls on Windows. I reported it on the helpdesk and they said they're gonna fix it.

    So if you want the program to run asynchronously or you want to target Ubuntu you should be fine. This is a Windows-only issue. Set the second argument to 0 on Windows and you should be all set. :)

    For example:
    Code:
    ExecuteShell("notepad.exe",0);
     
    Last edited: Oct 23, 2016
  5. RizbIT

    RizbIT Member

    Joined:
    Jun 24, 2016
    Posts:
    401
    no i mean right at the start when you define the external call in the dll... on the other guys dll sometimes on game start it crashed at that point
     
  6. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    As long as the wait parameter is 0, there is no crash. It's been thoroughly tested. No crash at game start. No crash after game start.
     
  7. renex

    renex Member

    Joined:
    Jun 23, 2016
    Posts:
    506
    Samuel Venable likes this.
  8. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    Great news everyone!

    Version 9.1.0 Released!

    • Finally fixed that nasty bug on Windows with setting the wait argument to true.

    • Added an optional third argument to allow opening files hidden on Windows.
     
  9. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    Thanks to @appleWolf, this extension is now 64-bit Mac compatible! Well, hopefully. I still need someone to test it. The code is portable for Unix-based operating systems. I already know it works on Linux, which is Unix-based.

    Mac is also based on Unix, and it built without any errors, so I can't imagine it not working, unless someone tries it on an unsupported architecture. If you would like to be a tester, shoot me a PM! If it works as intended, I'll announce Mac is officially supported at the top of the asset's description. :D

    (testers will be credited)
     
  10. ElChingles

    ElChingles Member

    Joined:
    Oct 13, 2017
    Posts:
    5
    Last edited: May 26, 2018
    Samuel Venable likes this.
  11. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    Version 9.3.0 Released!
    • Added official support for macOS.
     
  12. Gravityhamster48

    Gravityhamster48 Member

    Joined:
    Dec 6, 2018
    Posts:
    11
    Hello!

    I am new here, but definitely not new to Gamemaker. I hope this is an okay place to ask this question. It is directly related to your extension (which is a pretty cool piece of work, by the way).

    So I programmed an updater/launcher in Gamemaker for Windows that downloads the executable file for my game and saves it to the launcher's dedicated app data folder. I then execute the program with your extension. The problem comes when there are multiple users on the system. The process all works flawlessly on the primary user account, but then when the secondary user uses the launcher, it downloads just fine, but will not execute the program.

    Here is the code that defines the folder's location:
    Code:
    globalvar place;
    place = environment_get_variable("LOCALAPPDATA") + "\Updater";
    "Updater" being the name of the launcher I have created. I've tried using "game_save_id", "working_directory", and "program_directory". The latter two do not work and the first yields the same result.

    Here is the code that downloads the file. This code works perfectly no matter the user account. I'm just including it to give you an idea of what's going on here:
    Code:
    size = ds_map_find_value(async_load,"contentLength");
    progress = ds_map_find_value(async_load,"sizeDownloaded");
    if (perc < 100)
    perc = round((progress/size)*100)
    if (ds_map_find_value(async_load, "id") == async_ini)
    {
          var status = ds_map_find_value(async_load,"status");
          if (status == 0 && statussss < 2)
          {
                statussss = 3;
                ini_open("localversion.ini");
                ini_write_real('version','number',ver);
                ini_close();
                statussss = 4;
                instance_create(x,y,o_Launch);
          }
    }
    Finally, here is the code that launches the game (the game executable being called "GunCave.exe"):
    Code:
    timer++;
    if (timer >= 30*60)
    {
        if (file_exists(place+"\GunCave.exe"))
        {
            o_Updater.neednew = 6;
            if (timer >= 33*60)
            {
                ExecuteShell(place+"\GunCave.exe", true);
                game_end();
            }
        }
        else
        {
            o_Updater.neednew = 7;
            if (timer >= 33*60)
            {
                game_end();
            }
        }
    }
    This is where the problem lies. This code works on the primary user account, but not on the secondary account. On the primary account, it successfully launches my game and then closes the launcher once the game is closed. On the secondary account, the game fails to launch and the launcher closes.

    I know I've read places that have discouraged making a launcher in Gamemaker, but I was able to create and get it to work, up until this issue. I hope someone can help me.

    Thanks in advance,
    ~Gravityhamster
     
    Last edited: Dec 6, 2018
  13. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    @Gravityhamster48 Hey!

    What's the difference between the two accounts? Is one of them by any chance not administrative? Does it require administrative privileges to run the exe?
     
  14. Gravityhamster48

    Gravityhamster48 Member

    Joined:
    Dec 6, 2018
    Posts:
    11
    Thank you so much for replying!

    The executable does not require administrative privileges to run. Even so, though, I've tried making the secondary user both regular and administrator and the result is the same: The executable doesn't launch and the launcher program closes.
     
  15. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    Try removing the file_exists call. I'm interested in hearing if it runs the file after commenting that out. I might have a solution if that ends up being the problem.

    I'd also check if the path and file exists manually, outside of code, i.e. in explorer, and also what value the environment variable returns on both users by contrast.
     
    Last edited: Dec 6, 2018
  16. Gravityhamster48

    Gravityhamster48 Member

    Joined:
    Dec 6, 2018
    Posts:
    11
    It still does not work if I remove the "file_exists" call. I sent you in my original post the code for when it launches the game offline. If the the launcher detects that it cannot connect to my server to check for a new update, it will run the code I sent you. Otherwise, it checks for an update and runs this code instead, which has no "file_exists" present in it:
    Code:
    i++;
    if (i == 5)
    {
        ExecuteShell(place+"\GunCave.exe", true);
        game_end();
    }
    This code still does not launch the game correctly under the secondary account. (Obviously, it does run correctly under the primary account.)

    The executable file is present in the desired appdata folder and I can even manually execute the file from there and it runs fine. Also, when I run my launcher I draw the appdata directory (stored in variable "place") onto the screen. The directory is correct on both accounts, changing the username to match the current user account and matches the directory manually found in Windows Explorer.

    Hopefully that all makes sense. If you need clarification, please ask.
     
  17. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    I'm not sure even if I had your source code to debug with how much help that would be, it's really odd that it works on one account, but not the other. I hate to say it, but I'm stumped. Unless I can reproduce this issue myself, I don't see how I can figure out what's going wrong. :(
     
  18. Gravityhamster48

    Gravityhamster48 Member

    Joined:
    Dec 6, 2018
    Posts:
    11
    Oh well. Thanks for trying!... Maybe I'll just have to go at it with a different approach. Maybe even make a launcher in a separate language. I dunno.

    I will say that you can create the same basic scenario by following these steps: Make a new user on your computer. You can easily do this in the settings and don't even have to make a new Microsoft account to do it (and it can easily be deleted later). Create a new project in Gamemaker. Have the project write a text file (I prefer a .ini file) so that it creates the appdata directory for your project, then manually place any standalone executable in the appdata directory for your project (These steps must be done under BOTH user accounts). Make an "ExecuteShell" command to run that program you put in the project's directory. Now export the project to an executable and run it. It should run the executable that you placed in the appdata folder for your program under your primary user account, but it should not successfully run under the secondary account.

    If it's too much of a pain to try to figure out, don't worry about it, but there's some basic steps if you wish to try to reproduce the issue.
     
    Samuel Venable likes this.
  19. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    I'll give that a shot tomorrow. It's getting late where I live. I'll get back to you with the results of my testing.

    Edit:

    Trying it now as we speak...

    Edit2:

    It works for me on both accounts. Am I doing something wrong?

    I run this on account 1:

    Code:
    if (os_type == os_windows)
    {
        ini_open("test.ini");
        ini_write_real("hello", "world", 1);
        ini_close();
       
        if (file_exists(game_save_id + 'notepad.exe'))
            ExecuteShell('"' + game_save_id + 'notepad.exe"', true);
    }
    
    game_end();
    It created the ini file but the exe needs to be copied there in order to run so I do that.

    Then I hit run again.

    Export project.

    Do all the same as above but on account 2.

    It all worked for me. notepad.exe ran on both accounts after I copied it to the correct folder on both accounts.
     
    Last edited: Dec 6, 2018
    Gravityhamster48 likes this.
  20. Gravityhamster48

    Gravityhamster48 Member

    Joined:
    Dec 6, 2018
    Posts:
    11
    Yes! Thanks to you, it's fixed!!

    What I found out was that my syntax was incorrect. Here was the old code for the file path:
    Code:
    globalvar place;
    place = environment_get_variable("LOCALAPPDATA") + "\Updater";
    Execute:
    Code:
    i++;
    if (i == 5)
    {
        ExecuteShell(place+"\GunCave.exe", true);
        game_end();
    }
    And here is the new, working code for the file path execution:
    Code:
    i++
    if (i == 5)
    {
        ExecuteShell('"' + string(game_save_id) + 'GunCave.exe"', true);
        game_end();
    }
    I don't know if using "LOCALAPPDATA" rather than "game_save_id" would work, but it doesn't matter. I'd rather use "game_save_id" anyway. Here's the things I could note that you did differently compared to me:
    • First of all, you excluded the "\" before the executable.
    • Second, when I tried "game_save_id" I neglected to convert to a string.
    • Third, was the use of double and single quotes. Notice the difference between this:
      Code:
      place+"\GunCave.exe"
      and this:
      Code:
      '"' + string(game_save_id) + 'GunCave.exe"'
    • I also just removed the variable "place" for when I execute as a whole just to make it easier to implement the correct quotes and reduce confusion.
    Thank you so much for your help! I'm so glad that it was a problem with my code and not with the extension!

    You've been great to work with!
    ~Gravityhamster
     
    Samuel Venable likes this.
  21. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    I'm glad you've figured it out, and that I could help! Using the quotes within quotes is generally a good practice for command line stuff, since there are sometimes paths with spaces. Some path functions and variables do not include the final slash, but on Windows at least, I know working_directory and game_save_id have it. It may be different for getting the environment variables, as well as program_directory. I can't remember whether temp_directory has the last slash. In any case, I agree the inconsistency is a bit confusing and I have reported this to the bug tracker for GMS 1.4 and 2. However, they didn't fix it before the end of 1.4's lifetime, so your practice of using the extra slash is probably better, also because it is backwards compatible with pre-Studio GM versions.

    Edit:

    Also, as far as I know, you don't need to wrap game_save_id in a string() function. I did that by accident originally, but updated my post to remove that.
     
    Last edited: Dec 6, 2018
    Gravityhamster48 likes this.
  22. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    I have unfortunate news concerning the future of this project. It relies on Microsoft Script Control on Windows, i.e. "msscript.ocx" in your SysWOW64 folder, which is a legacy component built for 32-bit only by Microsoft. Normally I would just use CreateProcess or ShellExecute Windows API functions to achieve this, but for the wait parameter, a call to waiting for completion is necessary, and that crashes GameMaker due to a long-standing bug with GM's Runner.

    So anyway, I am relying on something that essentially does the same thing but with interpreted VBScript. This can be done with one of two mechanisms - Microsoft Script Control, which is 32-bit only. Or I could use the IActiveScript interface, which would also support the upcoming 64-bit Windows GM Runner, but ironically enough that crashes the Runner, just like CreateProcess and ShellExecute does, but only when the wait argument is true.

    As a final attempt to bypass all of this, i think I have good news as well. I just discovered while writing this post just now, that I can create an invisible modal dialog both the developer and the end user won't see, and allow that to create the waiting parameter to have the desired effect. Haven't tested it yet. Wish me luck! Will add my results in an edit.
     
  23. Gravityhamster48

    Gravityhamster48 Member

    Joined:
    Dec 6, 2018
    Posts:
    11
    That does sound unfortunate. I hope you can find a solution! However, if I do not receive a crash in my project as it stands now, do I need to worry about the bug?
     
  24. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    No, you don't. It only applied to certain methods that attempt to do the same thing. The current method doesn't do that.
     
    Gravityhamster48 likes this.
  25. BifTek

    BifTek Member

    Joined:
    Apr 18, 2019
    Posts:
    5
    Edit: Nevermind. This extension is great.
     
    Samuel Venable likes this.
  26. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    Hey fam, so i fixed the Linux version which a user reported to me that it got stale and stopped working. Without changing the code, I simply rebuilt it with the latest G++ compiler. They said it works again now. Please let authors/publishers know if you ever run into similar issues down the line using extensions, as all of them on the marketplace that are not pure GML will need to be rebuilt over time to maintain compatibility with the latest systems.

    This update only fixes the GMS 2.x version. If you need the update for GMS 1.4 please contact and I'll send you the new files. I can't update the 1.4 version on the MP anymore because YoYo's uploader for that version is still broken.
     
  27. the_dude_abides

    the_dude_abides Member

    Joined:
    Jun 23, 2016
    Posts:
    480
    I downloaded this earlier, and was testing it out. It ran fine with the example where you bring up notepad and the calculator, but I wanted to load up an exe of a gamemaker project. I could see it being started, but it would shut down after appearing.

    The aim is to see if I can get two versions of the project running in sync, and use it for multi-threading somehow. This is what I did (bare in mind I'm not that savvy...)

    ExecuteShell('"C:\Windows\System32\calc.exe"', true); // your original code

    ExecuteShell('C:\Users\jb209\Downloads\gamemaker stuff\market place stuff\test_project.exe', true); // my alteration - which I assumed was all that this was doing...giving the directory location?

    Can you please let me know what I'm doing wrong? I just want to know why it doesn't stay open, and yet the calculator does when called in the same way.
     
  28. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    Because there are spaces in that path, you will need to do:

    ExecuteShell('"C:\Users\jb209\Downloads\gamemaker stuff\market place stuff\test_project.exe"', true);
     
  29. the_dude_abides

    the_dude_abides Member

    Joined:
    Jun 23, 2016
    Posts:
    480
    Thanks for the help :) That fixed it.

    Does any part of this process give any control / communication between the two applications?

    EDIT:
    I've looked into networking, and have set up a project, so I imagine that covers it?
     
    Last edited: May 17, 2019 at 7:02 PM
  30. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    If you made the executable yourself that you are trying to run, you can communicate between the two by reading and writing to external files, is that what you meant?
     
    The Sorcerer likes this.
  31. the_dude_abides

    the_dude_abides Member

    Joined:
    Jun 23, 2016
    Posts:
    480
    I was initially thinking of reading and writing to files, though decided it's probably not the best way. The YOYO demo of the LAN platformer showed how to use networking on the same machine, and that seems simpler.

    Just wondered if there was anything inherent to execute shell that made doing the networking redundant (I still want to use it to open up the second exe though) , but I have the solution if it doesn't.
     
  32. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    Not that I know of, but I suppose it may be possible with shell scripts or something. I honestly don't know...
     
  33. the_dude_abides

    the_dude_abides Member

    Joined:
    Jun 23, 2016
    Posts:
    480
    Thanks anyway :)
     
    Samuel Venable likes this.
  34. The Sorcerer

    The Sorcerer Member

    Joined:
    Jan 3, 2019
    Posts:
    237
    You could communicate between applications via window handles, processes, etc.. but you'd have to have applications that are aware of each other. Not too hard to achieve, but is out of scope of this type of extension. Not really the sort of thing that a shell execute is designed to do.
     
  35. the_dude_abides

    the_dude_abides Member

    Joined:
    Jun 23, 2016
    Posts:
    480
    Thanks for the info. That sounds a bit beyond my capabilities (for now), but I have an alternative which should suffice.
     
  36. Samuel Venable

    Samuel Venable Time Killer

    Joined:
    Sep 13, 2016
    Posts:
    1,121
    @matharoo informed me he is in the process of making a tutorial that does exactly what @the_dude_abides is looking for, and he said he is using my Execute Shell extension to do it. I love it when I make something that has more practical uses than I originally anticipated. I'm sure you being a much more experienced developer than I am have run into this kind of thing a lot more than I have. Regardless, one day i will be as good as you, just wait and see you stinker. :p
     
  37. the_dude_abides

    the_dude_abides Member

    Joined:
    Jun 23, 2016
    Posts:
    480
    Thanks Samuel for tagging me into that - I will be interested in that tutorial when matharoo gets around to it. I guess for me it's just a question of which form of "communication" is the least costly and / or effective to do - local networking and sending limited data in a form that fits a buffer, or whatever matharoo' process entails (which will hopefully be more direct in communicating / manipulating data).

    But that's getting a bit off topic from your original thread, so I'll leave it there. Cheers!
     
    Samuel Venable likes this.
  38. The Sorcerer

    The Sorcerer Member

    Joined:
    Jan 3, 2019
    Posts:
    237
    You have been for a long time. You just don't realise it. :D

    [media][/media]
     
  39. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    781
    Legendary
     
    The Sorcerer likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice