Problem mit process.start



  • Ich hätte da mal eine Frage:
    Ich will von meinem Programm aus eine Datei mit Excel öffnen (process.start(Excelpfad, Dateipfad) )
    Funktioniert auch ganz wunderbar.
    Aber Excel meckert, das die Datei von "einen anderen Benutzer" bereits geöffnet ist und bietet mir das Fensterchen mit entweder schreibgeschützt öffnen oder benachrichtigen an.
    Klicke ich auf benachrichtigen und schließe mein Programm, meldet Excel, das die Datei freigegeben wurde.
    Dieses Verhalten passt mir leider überhaupt nicht.
    Wie kann ich das verhindern?
    Und eine zweite Frage hätte ich auch noch:
    Wie kann ich herausfinden, das eine Datei vollständig geladen wurde?
    Wenn ich mehrere process.start(Excelpfad, Dateipfad_x) nacheinander aufrufe,
    werden die Dateien nicht in dieser Reihenfolge geöffnet, sondern zuerst die kleineren und dann die aufwändigen mit vielen Bildern etc.
    Kann ich irgendwie die Reihenfolge erzwingen?



  • Die Process-Klasse hat einige Statische Methoden um momentan laufende Prozesse zu listen
    beide liefern ein Array von Process-Instanzen. Ja richtig gehört Dir stehen also
    im .NET 1.1 in dieser Klasse 2 statische Methoden dieser Klasse zur Verfügung

    **
    GetProcesses
    GetProcessesByName
    **

    beide liefern ein Array von Process-Instanzen.

    Über ein Codekonstrukt dieser 2 Möglichkeiten könntest Du beeinflussen in welcher Reihenfolge was gestartet werden soll.

    Zu Anfang startest Du das was zumindest zuerst gestartet werden soll
    dann in einer Schlefe Prüfen ob es schon läuft und das nächste Starten
    usw. und sofort.

    Eine Möglichkeit die mir jetzt so einfiel.

    Anderweitig wäre es möglich durch eingebunden WinAPI-Aufruf (unmangeed Code)
    dies abzuprüfen.

    Kann mir gut vorstellen das das .NET 2.0 in der Hinsicht noch andere Dinge anbietet.

    Achja da das gesamte Officepaket und dessen Tools Interoperabilität zur
    erfügung stellt wäre es möglci das Du Dich über deine C#-Anwendung als
    Client an diese MS-Office-Applikationsserverobjekt ranklinken tust.
    Sowas habe ich auf www.codeproject.com in Code gegossen schon gesehen.

    Dann kann deine C#-Anwendung das Office und seine Inhalte steuern als auch starten, manipulieren beenden. etc.

    für Excel
    http://www.google.de/search?hl=de&q=Excel+Automation+C%23&btnG=Google-Suche&meta=
    http://www.codeproject.com/csharp/Package.asp

    Aber auch nichtmicrosoft-Software bietet sowas ... sehr interessant sowas



  • Im Bezug auf dein Problem mit dem konkurrierende Zugriff mehrer Programminstanzen auf ein Datei, hmm ist klar warum das Betriebssytem/Excel meckert das jemand anderes schon das Ding benutzt.

    Also auf eine Excel-Datei greifen mehrer andere zu. Könntest Doch auch eine temporäre Kopie machen von der Datei Daten des Original in mehrer kopien.

    Die übrigen Insatnzen dann mit den Dateikopien starten.

    Wie Du aber hinterher die unter Umständen geänderten Informationen
    zu einer Datei zusammenführen willst das kannst nur Du wissen!

    Ich kenne ja nicht deine konkreten Vorstellungen über dein Programm.



  • An der geöffneten Datei wird nichts geändert, sie soll nur angesehen werden.
    Ich sterte mein Programm nur 1x. Welche Instanzen meinst du?
    Das Ziel des Programmes ist es, das man im c# Prog anklickt welche Excelfiles man ansehen will und diese dann in der richtigen Reihenfolge (zuerst die alten Daten, dann die Neuen, dann die Diagramme usw.) gestarten werden.
    Und zwar möglichst ohne Schreibgeschützt Meldung und eben in der richtigen Reihenfolge.



  • starchild schrieb:

    "einen anderen Benutzer" bereits geöffnet

    Kommt meistenz wenn zuvor schon ein Programm File-Handles auf diese Dateien hat!

    Kann es vielleicht sein das Du z.B. für diese Dateien FileStream-Objekte die vom Scope her Public,private etc. sind noch zur Programmlaufzeit noch hälst?
    Und das Du obwohl das diese Streams noch nicht abgebaut sind Du versuchst diese Dateien mit Excel aus dem Programm zu öffnen.

    Dann wäre es klar 2 Progrmme wollen sich eine Datei teilen!

    Dein C#-Programm hat schon die Datei und will es oder muss es mit Excel teilen.

    Gruss Sclearscreen



  • starchild schrieb:

    "einen anderen Benutzer" bereits geöffnet .... und schließe mein Programm, meldet Excel, das die Datei freigegeben wurde.

    Dein Programm bunkert bestimmt in irgendwelchen Arrays,Collections,Variablen

    die innerhalb der Klasse public,private,protected sind
    Streams,Filehandles die Du wahrscheinlich bei der Dateisuche beim Auflisten erzeugst.

    bevor Du über Process.Start (Excel mit Datei starten) loslegst muss sichergestellt werden
    das diese Objekte wenn sie in Arraylisten,Collections sind per Clear glöscht werden, oder das jedes einzelne per

    Dispose
    oder Zuweisung null freigegeben werden

    such und guckmal genau in Deinem C#-Programm nach es ist bestimmt so.
    In Deiner Aussage siehe wo ich Dich zitiere bestätigst Du meine Vermutung.
    Demnach hält Dein Programm was Excel mit dieen Dateien per Start versorgt
    über irgendlweche Objekte göffnete Streams auf diese Dateien.

    Gruss sclearscreen

    P.S.: Ich habe im Netz mal ein Nützliches Tool gefunden
    das kann anzeigen von welchen Programm eine Datei genutzt wird!
    nennt sich UnLocker weil man kann damit Dateien auch entsperren.
    D.h. Programme mit Gewalt von Ihren Ressourcen trennen.

    http://unlocker.softonic.de/ie/40696

    Du könntest Dein C#-Programm starten und dann damit auf eine Excel-Datei gehen
    wo Du selbst weisst die ist 100% mit im Boot und wird von meinem Programm aufgelistet. Genau die überprüfst Du mit dem Tool. Weil das Ding zeigt ja an von welchen Prozessen eine Datei benutzt wird.

    Da hätten Wir dann auf jeden Fall genau Aufschluss!



  • Also ich lese ein Verzeichnis mit folgendem Code ein und schreibe die Dateinamen in ein globales Stringarray filename[]
    Excel meckert aber immer noch, das die Datei benützt wird.

    private void OpenFiles_Click(object sender, System.EventArgs e) {
    FileInfo[] filelist={null};
    
    if (openFileDialog1.ShowDialog() != System.Windows.Forms.DialogResult.OK)
        return;
        string Dir = openFileDialog1.FileName;
    	Dir = Dir.Substring(0, Dir.LastIndexOf("\\"));  
    	FilenameOutput.Text = Dir;		
        DirectoryInfo di = new DirectoryInfo(Dir);
    	filelist = di.GetFiles();  //"*.DAT"
    	anzFiles = filelist.Length;
    	for (int i = 0; i < anzFiles; i++)
    	filename[i] = filelist[i].Name;
    }
    


  • ja ich sehe dabei auch nicht wo es klemmen kann. Du erinnerst Dich Doch noch an das Tool? Was ich Dir ans Herz gelegt habe.

    Hmm das Programm wenn ich mich zurückerinnere schreibst Du ja im Labor Deiner UNI.

    Müsstes gegebenenfalls mal Deinem Laborguru den Link von dem Tool geben das der mal abcheckt ds es harmlos ist. Es kann Dir sagen von welchen Programm eine Datei blockiert wird. Oder zeihst es Dir auf einen Rechner von einem Kumpel der das .NET SDK 1.1 auf seinem Kasten hat.

    Wirklich es würde Dir schneller zur Gewissheit verschaffen welches Programm der Übeltäter ist.

    FileInfo
    DirectoryInfo

    machen nur temporären kurzeitigen Zugriff auf Dateien und Verzeichnise wenn man deren, ich nenne sie mal, Servicmethoden aufruft bzw. nutzen diese dann intern bestimmt FileStream. Dieses Objekt kennt auch den Modus FileShare.
    Anderes wäre es halt wenn Du einen Stream auf eine Datei setzt, einmal sein Open aufrufst und solange das Programm läuft kein Close mehr machst.
    Ja dann hat ich Dir sagen können ja guck Dir mal diese Stelle an.

    Aber in deinem Code-Auszug ist von sowas nix zu sehen.

    Mein Rat also:
    Mach vorab zu Deinem Softwarsystem eine Liste welche Applikation[en]
    auf diese .xls-Files Zugreifen müsen, könnten und dürfen!
    Bring das Softwaresystem in Gang!
    Lass die Fehlermeldunge von Excel offen. Nimm jetzt besagtes Tool von dem ich sprach. Wechsele in den Ordner per Arbeitsplatz geh mit Rechtsklick auf die
    .xls-Files wähle aus dem Kontextmenü (was im Kontextmenü einen Eintrag hat)
    "Unlocker" aus dann siehst Du wirklich aus welcher Programminstanz der Zugriff
    auf die .xls-Datei erfolgt.
    Voraussetzung Du hast Dir den "Unlocker" installiert.



  • Es ist eindeutig meine c# Anwendung, die auf das Excelfile zugreift.
    Wen ich beim in Excel erscheinenden Dialog aus "Benachrichtigen" klicke und mien Programm schließe, meldet Excel, das die Datei freigegeben wurde und bietet an, sie zum schreiben zu öffnen.
    Programme installieren ist leider nicht so einfach. (sehr restriktive Richtlinien)



  • haha was mir jetzt einfiel habe ja Excel hier bei mir am start

    Excel kann man ja doppel und dreifach vierfach aufmachen
    es tummeln sich dan mehrer Excel-Tasks daran kann es auch liegen

    Eine Excel hat Deine Datei
    Du klickst wie wild auf Excel und die eine Excel-Instanz regt sich dann
    auf das noch andere Excel-Brüder/Schwestern/Verwandte/Erbschleicher auftauchen
    die auch anspruch auf diese Dateien erheben! Wobei mir unbekannt ist ob Excel vor der Öffnung immer eine Kopie macht. Ich bin ja schliesslich kein Excel-Entwickler.

    Du musst also vorher abchecken durch Code ob schon Excel läuft und ob das Excelinstanzen sind die schon Datei nutzen die in deiner Liste sind!

    Lösungsmöglichkeit Office-Automation auch bekannt unter Interoperabolität.
    Der Namensraum System.Diagnostics sollte hier auch wieder brauchbare Sachen dazu beisteuern können!



  • starchild schrieb:

    Es ist eindeutig meine c# Anwendung, die auf das Excelfile zugreift.
    Wen ich beim in Excel erscheinenden Dialog aus "Benachrichtigen" klicke und mien Programm schließe, meldet Excel, das die Datei freigegeben wurde und bietet an, sie zum schreiben zu öffnen.
    Programme installieren ist leider nicht so einfach. (sehr restriktive Richtlinien)

    Kann es sein da Excel auch mit .csv-Dateien arbeiten Tut das Du in Deiner IDE
    jedesmal wenn Du es öffnest auch eine solche Datei mit aufmachst.



  • Wo zeigst Du eigentlich die geordneten Datein in deiner C#-Anwendung an?

    In einer ListBox um sie von da per Klick zu staretn was dann über

    Process.Start läuft.



  • Das Problem folgendermassen aus ..... wenn Du diese Dateien jedesmal wenn Du eine Datei aus der ListBox wählst müsste wenn Du daraufihn im SelectItem-Delegaten
    der Listbox mit den .xls-Files, aufrufst. Innerhalb dieser DelegatenCallbackMethode rufst du dann bestimmt

    Process.Start(SeletedItem.....); immer ein extra Excel-Instanz auf!
    Wenn Du an der Stelle in der ListBox 2mal dieselbe Datei aufmachst,
    Hast Du aus Deiner C#-Anwendung heraus einen Neuen Excel-Nachkommen erstellt
    der auf die gleiche xls-Datei zugreift wie ein Excel-Vorfahre schon zuvor!

    Lösung dafür anders machen per Automation/Interoperabilität:
    Eine Excel-Instanz wird hierbei von deiner C# anwendung kontrolliert.
    Aus C# heraus kannst Du dieser einen Excel-Marionette sagen öffne diese Datei tue das usw.. Du kommst damit vom Process.Start-Ansatz weg, der unter Umstaänden für mehrfaczugriffe auf .xls-Files sorgt.



  • Ich verwende folgenden Code zum auswählen und Starten.
    Umgehe ich testweise die Listbox, indem ich Process.Start direkt einen String übergebe, wird die Datei ohne meckern geöffnet.
    Es liegt also tatsächlich an der Listbox Komponente.
    Gibt es eine Alternative?

    private void Open_Click(object sender, System.EventArgs e) {
      string item = listBox1.Items[listBox1.SelectedIndex].ToString();
    
    string filepath = @filename[int.Parse(item.Substring(10, item.IndexOf(":")-10))-1];
    string excelpath = @PathToExcel.Text;
      Process.Start(excelpath, filepath);
    }
    


  • starchild schrieb:

    Gibt es eine Alternative?

    Die hatte ich in meiner Antwort vor Deiner Antwort ja schon angedeutet!
    Process.Start in Deinem Anwendungskontext weglassen.

    Office-Automation verwwenden genauer Excel-Automation Stichwort Interoperabilität verwenden.

    Deine C#-Anwendung macht damit eine Excel-Instanz zu Ihrer Marionette.
    Ist eine ganz legale Technik die von Microsoft mit Werbung für .NET propagiert wird.

    Damit sagts Du zur marionette lade die Datei mache mit der datei das .....
    usw. und sofort.

    Wie bei Process-Start kannst du darüber eine Excel-Instanz starten
    als auch versuchen eine laufende Excel-Instanz über dein C#-Programm
    zur Marionette zu machen.



  • http://www.codeproject.com/info/search.asp?cats=3&searchkw=Excel+Automation&Submit1=Search&author=&sd=15+Nov+1999&ed=4+Aug+2006

    Selbst der Mozilla-Browser lässt sich fernsteuern, diese Interoperabilität
    ist mein persöhnlicher Kracher/Favorit/C#-Droge/Abhängigkeit. Und ein Argument warum ich mich C#
    abgebe. Naja ich will mal nicht übertreiben sonst kommt noch jemand mit einer weissen Jacke.... *lach*

    Aber ich findes es eine super Sache.



  • Eigendlich hätte ich ja nur die Datei einfach öffnen wollen...
    Aber so werde ich mir das ganze Automatisationszeug nur mal ansehen müssen.
    Danke für die Hilfe!



  • starchild schrieb:

    Eigendlich hätte ich ja nur die Datei einfach öffnen wollen...
    Aber so werde ich mir das ganze Automatisationszeug nur mal ansehen müssen.
    Danke für die Hilfe!

    Was willst Du machen wenn Excel so gestrickt ist und pro ein Process.Start
    eine extra Excel-Instanz/Task aufmacht.

    http://www.mycsharp.de/wbb2/thread.php?threadid=19410



  • hier ich bekomme zwar bei einem direkten using Excel einen Fehler

    "Appliction mehrdeutig"

    aber habe ich umgangen bei meinem .NET 1.1 bekomme ich excel über C# so Excel (als Marionette eines C#-Prog.) an den Start

    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Data;
    using DasExcel = Excel; // ein using Excel; führt zu einem mehrdeutigen Vereiss bei mir dann eben so
    
    namespace ImagesInAssembly
    {
    	/// <summary>
    	/// Zusammenfassung für Form1.
    	/// </summary>
    	public class Form1 : System.Windows.Forms.Form
    	{
    		/// <summary>
    		/// Erforderliche Designervariable.
    		/// </summary>
    		private System.ComponentModel.Container components = null;
    
    		DasExcel.ApplicationClass excelApp = null;
    		public Form1()
    		{
    			//
    			// Erforderlich für die Windows Form-Designerunterstützung
    			//
    			InitializeComponent();
    
    			//
    			// TODO: Fügen Sie den Konstruktorcode nach dem Aufruf von InitializeComponent hinzu
    			//
    			excelApp = new Excel.ApplicationClass();
    			excelApp.Visible = true;
    
    		}
    

    funktioniert nat. nur wenn Du einen verwies auf ein COM-Assembly in den Projekt bringst

    "Microsoft Excel Object Library 10.0" oder so heisst das

    jo und dann starte dei C#-Applikation und es macht eine Marionette von Excel auf jo es funzt toll



  • funktioniert bei mir beides

    eine schon laufende Excelinstanz zur Marionette machen
    wenn noch kein Excel im System rumkraucht eben eine Marionette selbst aufmachen!

    using System;
    using System.Drawing;
    using System.Collections;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.Data;
    using DasExcel = Excel;
    
    namespace ImagesInAssembly
    {
    	/// <summary>
    	/// Zusammenfassung für Form1.
    	/// </summary>
    	public class Form1 : System.Windows.Forms.Form
    	{
    		/// <summary>
    		/// Erforderliche Designervariable.
    		/// </summary>
    		private System.ComponentModel.Container components = null;
    
    		private DasExcel.Application excelApp = null;
    		public Form1()
    		{
    			//
    			// Erforderlich für die Windows Form-Designerunterstützung
    			//
    			InitializeComponent();
    
    			//
    			// TODO: Fügen Sie den Konstruktorcode nach dem Aufruf von InitializeComponent hinzu
    			//
    
    			// Versuch eine vielleicht schon laufende Excel-Instanz zur Marionette zu machen
    
    			try
    			{
    				object oApp = Marshal.GetActiveObject("Excel.Application");
    				excelApp = (Excel.Application) oApp;
    			}
    			catch{}
    
    			if(excelApp == null) // kein laufendes Excel gefunden
    			{
    				// Marionette selbst aufmachen
    				excelApp = new Excel.ApplicationClass();
    				excelApp.Visible = true;
    			}
    
    		}
    ..
    

Log in to reply