Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Is it possible to run another program from a Unity executable?

Discussion in 'Scripting' started by Reverend-Speed, Sep 18, 2019.

  1. Reverend-Speed

    Reverend-Speed

    Joined:
    Mar 28, 2011
    Posts:
    181
    I imagine the answer is going to be NO, for obvious reasons, but I'm looking for a way to sync an external audio player so that it starts at the same time as a Unity VR experience.

    This would be in relation to this project, where it would be another way to get around the limitations of Unity's audio capabilities.

    Any suggestions are much appreciated!
    --Rev
     
  2. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    816
    You could get Unity to run batch files which then run other programs. Its a whole other world of scripting to learn though
    https://stackoverflow.com/questions...h-file-without-leaving-the-console-open-after

    Also the batch files will most likely be only able to perform one specific task via command by Unity, so youll have to enumerate through how many different things or variations of said thing you need to run, and make that many batch files. It will work, its just horribly tedious. treat it as a backup of backups i suppose.

    EDIT:
    running a batch file from Unity
    https://forum.unity.com/threads/running-batch-file-from-c-script.338710/
     
  3. Jorhoto

    Jorhoto

    Joined:
    May 7, 2019
    Posts:
    20
    I guess antivirus won't like that.
     
  4. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,420
    No, your guess is wrong. And antivirus wont care until you want to start some suspicioius executable instead of normal system or user program. Check out Process class documentation in MSDN in order to learn how to start external programs and control them with C# and .Net. This will work in unity windows editor and player as normally should.
     
  5. Reverend-Speed

    Reverend-Speed

    Joined:
    Mar 28, 2011
    Posts:
    181
    Thank you @Laperen . God, I haven't looked at Batch files in a dog's age. Ergh. I'm mostly a Unity guy, but I guess if it's my only option... although...!

    I don't suppose anybody would have a suggestion for doing something similar with a website, if Unity could change a value or run a file there? Ultimately, I just need to have an audio file start at the same time as the Unity experience begins...?

    @Jorhoto - yeah, Antivirus will be a massive block here. That said, the program is only going to run on one computer, so if disconnected from the net and airgapped, presumably the computer's antivirus could be turned off...!
     
  6. palex-nx

    palex-nx

    Joined:
    Jul 23, 2018
    Posts:
    1,420
    No, it is impossible to start process from a browser due to browsers security restriction. Why can't you just play it via html5 audion or from within unity? Bot have builtin players, no need to code anything except calling .Play() method.
     
  7. Reverend-Speed

    Reverend-Speed

    Joined:
    Mar 28, 2011
    Posts:
    181
    Hey @palex-nx - sorry, was unclear, when I said 'run a file there', I was thinking of triggering some HTML5 audio on a web page, similar to your suggestion (wouldn't be running Unity in a browser for this).

    I'd love to do this in Unity, but the project specifically requires a set of multitrack audio files to be played on an array of speakers in sync with the main, on the rails, VR experience.

    I'm not particularly experienced with HTML5, so if somebody can suggest a method or point me in the direction of useful research on this, I'd appreciate it.

    Thanks very much so far, guys...!

    EDIT: This looks pretty promising: https://www.technical-recipes.com/2016/how-to-run-processes-and-obtain-the-output-in-c/
     
  8. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    14,756
    Unless you have an extremely misbehaving antivirus, in which case you should switch it for a reputable one, it won't care about one process spawning another as this is an entirely normal behaviour for a computer program. Many applications spawn other processes behind the scenes on a regular basis. Including antivirus programs.
     
  9. Reverend-Speed

    Reverend-Speed

    Joined:
    Mar 28, 2011
    Posts:
    181
    Hey folks, having success with starting the process - at least I've got VLC starting from Unity. =D

    There's a slightly problem, however, as this will be happening while the 'player' is in VR - so I'm wondering if we could start VLC in the background rather than take focus over the VR program...?

    Thanks so much for your advice so far folks...!
     
  10. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    6,749
    If you want to start another process, use the 'Process' class (yep, it's just called Process):
    https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process?view=netframework-4.8

    If you want to capture its output, as in if it's a command line process that outputs to the screen, there is the 'StandardOutput':
    https://docs.microsoft.com/en-us/do....process.standardoutput?view=netframework-4.8

    The Process class and its ProcessStartInfo has several different properties to control how the process is started up. Including hiding windows, starting with window minimized, running it as command line and hiding the output, and more. You can look through the properties to see what's available.

    Or, if you know exactly what behaviour you want, you can google those specific needs in relation to the 'Process' class... or just ask here.

    MIND YOU, this is a .net topic, and not really Unity related. Unity just uses mono/.net. So you don't need to google relative to Unity. Just google relative to C#/.net.
     
    eisenpony likes this.
  11. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    14,756
    VLC has advanced command line parameters that let you tell it not to open a window, to play a file, and then when it's done playing exit the application.

    Code (csharp):
    1.  
    2. vlc -I null --play-and-exit "C:\Windows.old\Users\Public\Music\Sample Music\Kalimba.mp3"
    3.  
    Alternatively you can force an application into the foreground. Using this method you would start the application and then you would force your game back to the foreground.

    https://stackoverflow.com/questions...a-process-in-the-background/31628004#31628004
     
    lordofduct likes this.
  12. eisenpony

    eisenpony

    Joined:
    May 8, 2015
    Posts:
    819
    I was going to suggest taking the same approach as lordofduct.

    Process and ProcessStartInfo.WindowStyle should be enough to get what you need without using batch files.

    I think the challenging part of this task will be getting VLC and Unity synchronized, unless the timing of the soundtrack vs the VR display isn't important.
     
  13. Reverend-Speed

    Reverend-Speed

    Joined:
    Mar 28, 2011
    Posts:
    181
    This is honestly one of the best, most comprehensive responses I've had to a question on this forums, and I've had a lot of good responses before. Thank you @Laperen , @johotto , @palex-nx , @Ryiah , @lordofduct and @eisenpony !

    I've had some good results already with these techniques, looking forward to trying out more tomorrow.

    Syncing with Reaper is going to be tricky, as you say, but I'm hopeful that the general ambiance will not require perfectly matched timelines...

    ...otherwise I'll be running crying back to here...
     
  14. Reverend-Speed

    Reverend-Speed

    Joined:
    Mar 28, 2011
    Posts:
    181
    In case anybody's curious, here's the code I've got so far - not perfect (I'd prefer to run Reaper in the background from the start and it'd be nice to have Unity always maintain foreground focus), but it works...! (Any landing you can walk away from...)

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System;
    5. using System.Diagnostics;
    6.  
    7. public class ProcessStarterTest01 : MonoBehaviour
    8. {
    9.     public float delay = 5.0f;
    10.  
    11.     private Process reaper;
    12.  
    13.     private IntPtr unityWindow;
    14.  
    15.     [System.Runtime.InteropServices.DllImport("user32.dll")]
    16.     static extern IntPtr GetActiveWindow();
    17.  
    18.     [System.Runtime.InteropServices.DllImport("user32.dll")]
    19.     static extern bool SetForegroundWindow(IntPtr hWnd);
    20.  
    21.     [System.Runtime.InteropServices.DllImport("user32.dll")]
    22.     static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
    23.  
    24.     const int ALT = 0xA4;
    25.     const int EXTENDEDKEY = 0x1;
    26.     const int KEYUP = 0x2;
    27.  
    28.     // Start is called before the first frame update
    29.     void Start()
    30.     {
    31.         reaper = new Process
    32.         {
    33.             StartInfo = new ProcessStartInfo
    34.             {
    35.                 FileName = "C:/Program Files/REAPER (x64)/reaper.exe",
    36.                 WorkingDirectory = @"C:/Program Files/REAPER (x64)",
    37.                 Arguments = "-nosplash",
    38.                 UseShellExecute = false,
    39.                 RedirectStandardOutput = true,
    40.                 CreateNoWindow = true,
    41.                 WindowStyle = ProcessWindowStyle.Hidden
    42.             }
    43.         };
    44.     }
    45.  
    46.     // Update is called once per frame
    47.     void Update()
    48.     {
    49.         if (Input.GetButtonDown("Fire1"))
    50.         {
    51.             unityWindow = GetActiveWindow();
    52.  
    53.             reaper.Start();
    54.  
    55.             StartCoroutine(RefocusWindow(delay));
    56.         }
    57.  
    58.         if(Input.GetButtonDown("Fire2"))
    59.         {
    60.             UnityEngine.Debug.Log("Trying to close.");
    61.             reaper.CloseMainWindow();
    62.             reaper.Close();
    63.         }
    64.     }
    65.  
    66.     private void SendUser()
    67.     {
    68.         unityWindow = GetActiveWindow();
    69.  
    70.         Application.OpenURL("http://example.com");
    71.  
    72.         StartCoroutine(RefocusWindow(0.0f));
    73.     }
    74.  
    75.  
    76.     private IEnumerator RefocusWindow(float waitSeconds)
    77.     {
    78.         // wait for new window to appear
    79.         yield return new WaitWhile(() => unityWindow == GetActiveWindow());
    80.  
    81.         yield return new WaitForSeconds(waitSeconds);
    82.  
    83.         // Simulate alt press
    84.         keybd_event((byte)ALT, 0x45, EXTENDEDKEY | 0, 0);
    85.  
    86.         // Simulate alt release
    87.         keybd_event((byte)ALT, 0x45, EXTENDEDKEY | KEYUP, 0);
    88.  
    89.         SetForegroundWindow(unityWindow);
    90.     }
    91. }
    92.  
    93.  
    94.