none
C#, Script, 4 Programme korrekt starten, platzieren, wie? RRS feed

  • Frage

  • Hallo,
    ich habe 2 eigene Programme, die ich platzieren kann.
    
      private void frmRMES_FormClosing(object sender, FormClosingEventArgs e)
        {
          Properties.Settings.Default.MyfrmState = this.WindowState;
          if (this.WindowState == FormWindowState.Normal)
          {
            Properties.Settings.Default.MyfrmSize = this.Size;
            Properties.Settings.Default.MyfrmLoc = this.Location;
          }
    			
    2 fremde, die ich platzieren möchte.
    
    a) möglich in C#?
    b) Wenn ja wie?
    c) was gibt es?
    
    http://www.sps-forum.de/showthread.php?t=480
    http://www.autoit.de/index.php?page=Thread&threadID=5322
    http://www.autoitscript.com/site/
    
    Was nimmt Ihr?
    
    Grüße Andreas
    
    -- geht nicht richtig mit autoitscript
    ShellExecute('C:\bES\bin\Debug\fremd1.exe')
    ;SetWinDelay, 1000
    WinMove ("C:\bES\bin\Debug\fremd1.exe", "", 10,10,200,300)
    
    Mittwoch, 25. Mai 2011 08:11

Antworten

  • Hallo Andreas,

    Dienst ist hier nicht richtig - das macht man eher bei lang laufenden nicht interaktiven Aufgaben - bei Dir hast Du aber eben zum Beispiel anzuzeigende Fenster etc. 

    Also TaskScheduler oder AutoStart ist ok. Einfacher ggf. erstmal AutoStart.
    Aber das sind jetzt im Prinzip schon "neue" Fragen.

    Das Schliessen ggf. auch mit "this.Close()" bei einer Windows Forms Anwendung (aber die Application.ExitThread-Methode deckt i.d.R. mehr Fälle ab).

     


    ciao Frank
    Freitag, 27. Mai 2011 11:16

Alle Antworten

  • Hallo Andreas,

    Prozesse/Programme startet man eigentlich über:

    [Process.Start]
    http://msdn.microsoft.com/de-de/library/0w4h05yb.aspx

    ---

    BTW: Das IMHO oft zusammenhanglose und doch etwas konfuse Geschreibsel erschwert es mir doch erheblich, deine Fragestellung zu erkennen. Was soll bspw. "c) Was gibt es?" und nachfolgend genannten Links mit der eigentlichen Frage "Wie starte ich ein Programm?" zu tun haben. Was soll "platzieren" sein? Was soll "geht nicht richtig mit autoitscript" sein? Was ist "autoitscript" überhaupt?

    Es wäre (wohl nicht nur für mich) hilfreich, wenn Du in deinen Posting nicht einfach nur stichwortartig das Problem anreißt sondern erklärst, was Du nun eigentlich genau machen willst und wo genau das Problem liegt.

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Mittwoch, 25. Mai 2011 09:07
    Moderator
  • Hallo Andreas,

    für externe Fenster (die nicht zu Deiner App gehören) bräuchte man es ansich nicht mit einem Script machen, sondern könnte einfach über folgendes implementieren:

    Hauptfenster des Prozesses: [Process.MainWindowHandle-Eigenschaft (System.Diagnostics)]
    http://msdn.microsoft.com/de-de/library/system.diagnostics.process.mainwindowhandle.aspx

    ShellExecute ist quasi: [Process.Start-Methode (System.Diagnostics)]
    http://msdn.microsoft.com/de-de/library/system.diagnostics.process.start.aspx

    Setzen der Fenster-Position: [pinvoke.net: setwindowpos (user32)]
    http://www.pinvoke.net/default.aspx/user32.setwindowpos

    Holen der Fenster-Position: [pinvoke.net: getwindowrect (user32)]
    http://www.pinvoke.net/default.aspx/user32.getwindowrect

    So könntest Du dann die Settings der externen Fenster setzen.

     


    ciao Frank
    Mittwoch, 25. Mai 2011 10:01
  • Es wäre (wohl nicht nur für mich) hilfreich, wenn Du in deinen Posting nicht einfach nur stichwortartig das Problem anreißt sondern erklärst, was Du nun eigentlich genau machen willst und wo genau das Problem liegt.

     


    Hallo Stefan,

    sei doch nicht gleich böse.

    Ich wollte zeigen, dass ich www.google.de eingesetzt habe, nichts brauchbares gefunden habe.

    Process.Start ist klar, kenne ich.

    http://dotnet-snippets.de/dns/externes-programm-aufrufen-SID32.aspx

    ZIEL:

    2 Exe Programme, die nicht!! von mir sind über den Bildschirm exakt zu positionieren.

    Also für den Anwender, als wäre es eins! Ein Programm noch im Hintergrund.

    So eine Art Scriptausführung.

    Da ist die Frage, ob so etwas über C# möglich ist.

    Wenn ja wie, WindowsPos ?!? wndTopMost? Not in Front?

    http://www1.minpic.de/bild_anzeigen.php?id=146678&key=77712934&ende

    Grüße Andreas

     

    Mittwoch, 25. Mai 2011 10:01
  • Hallo Frank, 
    nicht schlecht.
    Könnte es so gehen?
    
     const short SWP_NOMOVE = 0X2;
          const short SWP_NOSIZE = 1;
          const short SWP_NOZORDER = 0X4;
          const int SWP_SHOWWINDOW = 0x0040;
          Process[] processes = Process.GetProcesses(".");
          foreach (var process in processes)
          {
            var handle = process.MainWindowHandle;
            var form = Control.FromHandle(handle);
            if (form == null) 
        continue;
            SetWindowPos(handle, 0, 0, 0, form.Bounds.Width, form.Bounds.Height, SWP_NOZORDER | SWP_SHOWWINDOW);
          }
    
    
    Ich weiß wie das Program heißt.
     z.b. C:\Test\Fremd\F1.EXE
    Wie bekomme ich das Handle?
    
    Grüße Andreas
    
    http://stackoverflow.com/questions/1190423/using-setwindowpos-in-c-to-move-windows-around
    Mittwoch, 25. Mai 2011 10:34
  • Hallo Andreas,

    sei doch nicht gleich böse.

    bin ich nicht. Nur ist mir schon öfter aufgefallen, dass ich bei deinen Postings mehr Probleme habe, die eigentliche Fragestellung zu erkennen als das bei Fragen anderer User der Fall ist.

    ZIEL:

    2 Exe Programme, die nicht!! von mir sind über den Bildschirm exakt zu positionieren.

    Also für den Anwender, als wäre es eins! Ein Programm noch im Hintergrund.

    Da ist die Frage, ob so etwas über C# möglich ist.

    Das ist doch schon mal eher etwas, mit dem man was anfangen kann.

    Über Process.Start kannst Du das Programm starten, über die von Frank genannte Eigenschaft "MainWindowHandle" des Process Objekts erhältst Du das Handle.

    Dein angeführtes Codebeispiel passt nicht ganz, weil Du dort lediglich die vorhandenen Prozesse ausliest und keine eigene Prozesse startest, was Du ja aber wohl machen willst.

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community
    Mittwoch, 25. Mai 2011 10:51
    Moderator
  • Hallo Andreas,

    "Control.FromHandle(handle);" in Deinem Quellcode ist nur dann richtig, wenn Du es für managed Targets benutzt.
    Das wurde aber auch schon in Deinem Link angedeutet/gesagt (siehe Lösung dort) - ansonsten: ja, mit SetWindowPos geht das dann auch mit unmanaged Window-Handles.

     

    • Ich weiß wie das Program heißt.  z.b. C:\Test\Fremd\F1.EXE  Wie bekomme ich das Handle?

    häufig funktioniert folgendes:

    [Process.GetProcessesByName-Methode (String) (System.Diagnostics)]
    http://msdn.microsoft.com/de-de/library/z3w4xdc9.aspx

     

      Process[] procs = Process.GetProcessesByName("F1");
      MessageBox.Show(procs.First().Handle.ToString());
    

    wobei theoretisch ja auch andere Prozesse einen solchen Namen haben können.
    Deswegen vergleicht man möglichst viel - soviel, wie man eben über den Prozess weiß.
    Bei Bedarf wären dann diesbzgl. die Process-Eigenschaften eben abzufragen.
    ciao Frank
    Mittwoch, 25. Mai 2011 11:18
    • ... Ich weiß wie das Program heißt. z.b. C:\Test\Fremd\F1.EXE Wie bekomme ich das Handle?


    oder ggf. auch expliziter - je nach Anforderung:

     private void Form1_Load(object sender, EventArgs e)
     {
      string prozessDatei = @"c:\test\fremd\f1.exe";
      foreach (var p in Process.GetProcesses())
      {
      try
      {
       if (p.MainModule.FileName.ToLower() == prozessDatei)
       {
       MessageBox.Show("Handle von " 
        + Path.GetFileName(prozessDatei) + ": "
        + p.Handle.ToString());
       return;
       }
      }
      catch { }
      }
      MessageBox.Show("Prozess nicht gefunden");
     }
    
     

    ciao Frank
    Mittwoch, 25. Mai 2011 11:52
  • Hallo Frank,

    Danke. Das Handle bekomme ich.

    Jedoch keinen Zugriff. Dann geht es soch nicht, oder?

    http://www1.minpic.de/bild_anzeigen.php?id=146693&key=65685589&ende

    Noch eine Idee?

    Grüße Andreas

    Meine Tests

     public partial class frmTest : Form
      {
        //[DllImport("user32")]
        //public static extern int SetWindowPos(int hwnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
    
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool SetWindowPos(int hwnd, int hWndInsertAfter, int X, int Y, int cx, int cy, int wFlags);
    
    
    ....
    
     public frmTest()
        {
          InitializeComponent();
    
          const short SWP_NOMOVE = 0X2;
          const short SWP_NOSIZE = 1;
          const short SWP_NOZORDER = 0X4;
          const int SWP_SHOWWINDOW = 0x0040;
          Process[] processes = Process.GetProcesses(".");
          foreach (var process in processes)
          {
            if (process.ProcessName == "notepad++")
            {
              Process[] processNotepad = Process.GetProcessesByName("notepad++");
    
              SetWindowPos((int)process.Handle, 0, 0, 0, 33, 44, SWP_NOZORDER | SWP_SHOWWINDOW);
            }
    
    
    
            var handle = process.MainWindowHandle;
            var form = Control.FromHandle(handle);
            if (form == null) 
              continue;
    
            SetWindowPos((int)handle, 0, 0, 0, form.Bounds.Width, form.Bounds.Height, SWP_NOZORDER | SWP_SHOWWINDOW);
          }
    
        }
    // RICHTIG?
    ignoriert dank SWP_NOZORDER den 1. Parameter. 
    Es gibt ja folgendes
    GetDlgItem(IDC_BUTTON1)->SetWindowPos(&CWnd::wndTop,2,50,50,10,SWP_SHOWWINDOW); 
    GetDlgItem(IDC_BUTTON2)->SetWindowPos(&CWnd::wndBottom,2,70,50,10,SWP_SHOWWINDOW); 
    GetDlgItem(IDC_BUTTON3)->SetWindowPos(NULL,2,90,50,10,SWP_SHOWWINDOW); 
    GetDlgItem(IDC_BUTTON4)->SetWindowPos(this,2,110,50,10,SWP_SHOWWINDOW);
     
    
    
    Mittwoch, 25. Mai 2011 12:14
  • Das ist doch schon mal eher etwas, mit dem man was anfangen kann.

    Über Process.Start kannst Du das Programm starten, über die von Frank genannte Eigenschaft "MainWindowHandle" des Process Objekts erhältst Du das Handle.

    Dein angeführtes Codebeispiel passt nicht ganz, weil Du dort lediglich die vorhandenen Prozesse ausliest und keine eigene Prozesse startest, was Du ja aber wohl machen willst. 


    Hallo Stefan,

    ja richtig.

    Ich möchte die App öffnen und an richtiger Stelle positionieren. D.h. du hast meine  Aufgabe erkannt.

    Hast Du noch eine Lösung? Es geht nicht.

    Ich habe keinen Zugriff. Dann geht es doch nicht, oder?

    http://www1.minpic.de/bild_anzeigen.php?id=146693&key=65685589&ende

     

    Grüße Andreas

    Mittwoch, 25. Mai 2011 19:24
  • Hallo Andreas,

    Du kannst natürlich nicht den Process.Handle nehmen (das ist ja kein Fenster-Handle), sondern das MainWindowHandle des Prozesses und das kann man mit SetWindowPos setzen. Etwa:

            if (process.ProcessName == "notepad++")
            {
              SetWindowPos((int)process.MainWindowHandle, 0, 0, 0, 333, 444, SWP_NOZORDER | SWP_SHOWWINDOW);
            }
    


    ciao Frank
    Mittwoch, 25. Mai 2011 21:07
  • Du kannst natürlich nicht den Process.Handle nehmen (das ist ja kein Fenster-Handle), sondern das MainWindowHandle des Prozesses und das kann man mit SetWindowPos setzen. Etwa:

    Hallo Frank,

    ok und Danke. Dann sollte es ja gehen, teste es später.

    Grüße Andreas

    Donnerstag, 26. Mai 2011 04:41
  • Hallo Frank,

    wie immer perfekt, Deine Tipps. Passt und tut.

    Ein Bitte noch.

    Ein fremdes Programm sollte Größe 0,0,100,200 haben und minimiert in der Taskleiste sein.

    Wo dreht man minimiert?

    Hast noch einen Tipp?

     Process P = new Process();
          P.StartInfo.FileName = @"C:\f1.EXE";
          Thread.Sleep(900);
          P.Start();
    
          Process P2 = new Process();
          P2.StartInfo.FileName = @"C\f2.EXE";
          Thread.Sleep(600);
          P2.Start();
    
    
     const short SWP_NOZORDER = 0X4;
          const int SWP_SHOWWINDOW = 0x0040;
          Process[] processes = Process.GetProcesses(".");
          foreach (var process in processes)
          {
            if (process.ProcessName == "SCANNERV23")
            {
              SetWindowPos((int)process.MainWindowHandle, 0, 0, 0, 333, 444, SWP_NOZORDER | SWP_SHOWWINDOW);
            }
          }
    

    Gruß, Andreas

    Donnerstag, 26. Mai 2011 15:12
  • Hallo Andreas,

    • Wo dreht man minimiert?

    [How do I maximize/minimize applications programmatically in C#?]
    http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/9bde4870-1599-4958-9ab4-902fa98ba53a/

    also zum Beispiel etwas wie:

      public partial class Form1 : Form
      {
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool SetWindowPos(IntPtr hwnd, 
          int hWndInsertAfter, int X, int Y, int cx, int cy, SWP wFlags);
    
        [Flags]
        enum SWP
        {
          /// <summary>Setzt die aktuelle Z-Order zurück</summary>
          SWP_NOZORDER = 0x4,
          /// <summary>Zeigt das Fenster an.</summary>
          SWP_SHOWWINDOW = 0x0040
        }
    
        enum SW
        {
          /// <summary>In normale Größe anzeigen</summary>
          SW_SHOWNORMAL = 1,
          /// <summary>Minimiert anzeigen</summary>
          SW_SHOWMINIMIZED = 2,
          /// <summary>Maximiert anzeigen</summary>
          SW_SHOWMAXIMIZED = 3
        }
    
        [DllImport("user32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, SW nCmdShow);
    
        public Form1()
        {
          InitializeComponent();
    
          Process[] processes = Process.GetProcesses();
          foreach (var process in processes)
          {
            if (process.ProcessName == "notepad++")
            {
              IntPtr fensterHandle = process.MainWindowHandle;
              SetWindowPos(fensterHandle, 0, 0, 0, 100, 200,
                SWP.SWP_NOZORDER | SWP.SWP_SHOWWINDOW);
              ShowWindowAsync(fensterHandle, SW.SW_SHOWMINIMIZED);
            }
          }
        }
      }
     


    ciao Frank




    Donnerstag, 26. Mai 2011 15:39
  • Hallo Frank,
    ja das passt super.
    
     
    Ich stelle mit das so vor.
    Autostart Verknüpfung.
    Alles wird geöffnet, korrekt platziert.
    Der Manager schließt sich selbst.
    
    Hast Du noch einen weiteren Tipp.
    
     a) Dienst? 
       Geht so was schnell?
     b) Application.ExitThread();
         sollte auch reichen, oder wie ist Deine Erfahrung?
    Grüße Andreas
    
     private void AutoRun()
        {
          const short SWP_NOZORDER = 0X4;
          const int SWP_SHOWWINDOW = 0x0040;
          Process[] processes = Process.GetProcesses(".");
          foreach (var process in processes)
          {
            if (process.ProcessName == txtProcessName.Text)
            {
              SetWindowPos((int)process.MainWindowHandle, 0,
                Convert.ToInt32(txtX1.Text),
                Convert.ToInt32(txtX2.Text),
                Convert.ToInt32(txtWidth.Text),
                Convert.ToInt32(txtHeight.Text),
                SWP_NOZORDER | SWP_SHOWWINDOW);
    
              IntPtr hWnd = process.MainWindowHandle;
              if (!hWnd.Equals(IntPtr.Zero))
              {
                if (rB_Style3_Nothing.Checked == true)
                {
                  ShowWindowAsync(hWnd, SW_SHOWNORMAL);
                }
                else if (rB_Style2_Maximize.Checked == true)
                {
                  // SW_SHOWMAXIMIZED to maximize the window
                  // SW_SHOWMINIMIZED to minimize the window
                  // SW_SHOWNORMAL to make the window be normal size
                  ShowWindowAsync(hWnd, SW_SHOWMAXIMIZED);
    
                }
                else if (rB_Style1_Minimize.Checked == true)
                {
                  ShowWindowAsync(hWnd, SW_SHOWMINIMIZED);
                }
              }
            }
          }
          Application.ExitThread();
        }
      }
    
    Freitag, 27. Mai 2011 08:35
  • Hallo Andreas,

    Dienst ist hier nicht richtig - das macht man eher bei lang laufenden nicht interaktiven Aufgaben - bei Dir hast Du aber eben zum Beispiel anzuzeigende Fenster etc. 

    Also TaskScheduler oder AutoStart ist ok. Einfacher ggf. erstmal AutoStart.
    Aber das sind jetzt im Prinzip schon "neue" Fragen.

    Das Schliessen ggf. auch mit "this.Close()" bei einer Windows Forms Anwendung (aber die Application.ExitThread-Methode deckt i.d.R. mehr Fälle ab).

     


    ciao Frank
    Freitag, 27. Mai 2011 11:16
  • Dienst ist hier nicht richtig - das macht man eher bei lang laufenden nicht interaktiven Aufgaben - bei Dir hast Du aber eben zum Beispiel anzuzeigende Fenster etc. 


    Hallo Frank,

    ok, dann schließen wir es hier mal ab.

     

    Danke nochmals.

    Grüße Andreas

    Freitag, 27. Mai 2011 12:02