0

Hello Stack Overflow community,

I have been working on making a custom installer/launcher for the game I am making, it is currently in working in a non-portable context, however if I want to put it inside of a game for distribution, it must work inside of a portable context (i.e. it should not access the drive for any of it's own needs, only the other software's needs)/

At the current moment it loads a song from the drive to play, and as well loads the prerequisites for the game if the launcher has never been opened before or did not finish successfully. The files are all set to "EmbeddedResource" inside of SharpDevelop, and they are part of the final compiled script.

However, in the code's current context, the script still has to access the drive to do all of those functions, even when they are embedded into the final program.

The current code I have so far is below, "programpath" refers to the directory of which the file is being executed from, "MainText" is the main output window, which is better seen in this Stack Overflow question, and label1 is a debug line, that is only used to show the path of the current running command (will be removed when all the things are embedded).

public MainForm()
    {
        //Open Window
        InitializeComponent();
        CenterToScreen();
        //Start song
        System.Media.SoundPlayer player = new System.Media.SoundPlayer(programpath+"\\Resonance.wav");
        player.PlayLooping();
        this.Shown+=(s,e)=>{
            if(File.Exists(programpath+"\\FirstLaunch.lic")&&File.ReadAllText(programpath+"\\FirstLaunch.lic").IndexOf("Installation Successful")>=0){
            BackColor=System.Drawing.Color.OrangeRed;
            MainText.BackColor=System.Drawing.Color.OrangeRed;
            MainText.ForeColor=System.Drawing.Color.Aquamarine;
            MainText.Text="Starting game..";
            Process game = new Process();
            //placeholder executable, will be finished game executable
            game.StartInfo.FileName="D:\\UT2004\\System\\UT2004.exe";
            game.StartInfo.ErrorDialog=true;
            game.Start();
            //stop playing music, 
            player.Stop();
            //when game stops, close the launcher
            game.WaitForExit();
            Application.Exit();
            }else{
                //Start prerequisite installation
                newLaunch();
            }
        };
}
    //if the launcher has not been open before OR the last installation was not successful
        void newLaunch(){
        //Creates and makes a stream to the file
        StreamWriter writer = new StreamWriter(programpath+"\\FirstLaunch.lic");
        //Changing color scheme
            BackColor=System.Drawing.Color.Chartreuse;
            MainText.BackColor=System.Drawing.Color.Chartreuse;
            MainText.ForeColor=System.Drawing.Color.Black;
            MainText.Text="Configuring Prerequisites....\nInstalling DirectX";
            //write to file about stage
            writer.Write("Installing DirectX");
            //start DirectX installer
            Process prerequisite = new Process();
            prerequisite.StartInfo.FileName=programpath+"\\dxwebsetup.exe";
            prerequisite.StartInfo.ErrorDialog=true;
            prerequisite.Start();
            //debug line
            label1.Text=programpath+"\\dxwebsetup.exe";
            //wait for installer to finish and close
            prerequisite.WaitForExit();
            //remove refernce to DirectX installer
            prerequisite.Close();
            //write to file about stage
            writer.WriteLine("...true");
            //Changing color scheme
            BackColor=System.Drawing.Color.DarkMagenta;
            MainText.BackColor=System.Drawing.Color.DarkMagenta;
            MainText.ForeColor=System.Drawing.Color.Yellow;
            MainText.Text="Configuring Prerequisites....\nInstalling Microsoft VC++2015 Update RC3";
            //write to file about stage
            writer.Write("Installing VCRedist");
            //start VC Redistributable installer
            prerequisite.StartInfo.FileName=programpath+"\\vc_redist.x86.exe";
            prerequisite.StartInfo.ErrorDialog=true;
            prerequisite.Start();
            //debug line
            label1.Text=programpath+"\\vc_redist.x86.exe";
            //wait for installer to finish and close
            prerequisite.WaitForExit();
            //remove reference to VC Redistributable installer
            prerequisite.Close();
            //write to file about stage
            writer.WriteLine("...true");
            writer.WriteLine("Installation Successful");
            writer.Close();
            //re-open launcher from open context
            label1.Text=programpath+"\\ColorLoop.exe";
            Process.Start(programpath+"\\ColorLoop.exe");
            Application.Exit();
        }
    }
}

How do I get the program to play the music, and load the pre-requisites from itself and not from separate drive files inside the code. It is all already embedded, just not being used.

  • You really should mention that you're using **`SharpDevelop`** IDE. Any solution to your question has to take this into count. The answer you got supposes a Visual Studio enviroment/methods. – Jimi Jun 13 '18 at 20:07
  • @Jimi is there a solution for SharpDevelop then? – NaturalistUbuntu Jun 13 '18 at 20:18
  • GitHub SharpDevelop: [Using Resources](https://github.com/icsharpcode/SharpDevelop/wiki/Using-Resources) -- [SharpDevelop- Cannot find embedded resource at design time](https://stackoverflow.com/questions/38934422/sharpdevelop-access-resource-file-settings). A Google search will yield more results. – Jimi Jun 13 '18 at 20:29

2 Answers2

1

I finaly figured it out, so I am answering my own question in the hopes that people who are struggling in the future can figure it out.

Using the link provided by @Jimi for Accessing Resources in SharpDevelop, and scrolling down to the "Embedding Files directly" section, shows the context at which to access Embedded Resource. The thing to note here is that the return type of GetManifestStream(string) is a System.IO.Stream object. This is important as we need SoundPlayer to accept a System.IO.Stream object some how. This can be done two ways, by using an overloaded constructor or Property of the SoundPlayer class. As defined by the MSDN page for the SoundPlayer Class.

However, when I tested this, I could not get the sound to play. Furthering my research, I found that Assembly.GetExecutingAssembly() has a accessible method named "GetManifestResourceNames()" that returns a string array of all the resources and their corrective names to access them. I was able to see the return by creating a Windows Form Label called "ExecutingAssem", and using the instructions from DotNetPerls to create a static method named "ConvertStringArrayToStringJoin()", but changing its seperator from "." to "|" to better read the assets.

With that in place the final program shows the list of embedded resources with the line: ExecutingAssem.Text=ConvertStringArrayToStringJoin(Assembly.GetExecutingAssembly().GetManifestResourceNames());

And the final program appearing as: Program showing all the resources in the corner

The interesting thing here is that the song resource (Resonance) is not actually a part of the Namespace, or MainForm...but rather its own name as the resource title.

With that missing information found, I needed to change the program from reading the drive to reading the manifest stream. Using the overloaded constructor that utilizes a System.IO.Stream object as a parameter instead of a string to a file location, I changed where the player object is initiated to use that constructor.

SoundPlayer player =new SoundPlayer(Assembly.GetExecutingAssembly().GetManifestResourceStream("Resonance"));

Finally the final application played the song with the ability to move the .exe file elsewhere and still be able to play the same song without "Resonance.wav" needing to be in the same directory.

-1
private void button1_Click(object sender, EventArgs e)
{
    SoundPlayer player = new SoundPlayer();

    //Add TestSound.wav file to the built-in resource file Project>Properties>Resources.resx
    player.Stream = Properties.Resources.TestSound;

    //Add TestSound.wav file to a new resource file Resource1.resx
    //player.Stream = Resource1.TestSound;
    player.Play();
}
kapantzak
  • 11,610
  • 4
  • 39
  • 61
  • I think you forgot to format your comment....But I was able to drop it into a IDE, and decipher it, it seems to only apply to a context with Resource.resx files...I am not sure that EmbeddedResources are handled the same way. – NaturalistUbuntu Jun 13 '18 at 06:09
  • On further inspection, it seems like you cannot reference Embedded Resources as a Resource resx. Also the Properties system does not work in the context you provided. Thank you for the suggestion however. – NaturalistUbuntu Jun 13 '18 at 06:10