I'm trying to control access via a multi-process console application, so that only one process can run a specific part of the code at a time.
Actually, I would have liked to use a mutex for this, but the Mutex class doesn't seem to work on Linux.
My code:
using var mutex = new Mutex(false, #"Global\TestMutex");
if (mutex.WaitOne(0, false)) {
Console.WriteLine("Mutex erhalten");
} else {
Console.WriteLine("Mutex nicht erhalten");
}
Console.WriteLine("Beliebige Taste drücken zum beenden.");
Console.ReadKey();
Working on Windows:
Not working on Linux (Ubuntu 22.04/NET6):
Am I missing something?
My current workaround ist to have a "Lockfile" but I didn't want to maintain an additional utility class.
utility class:
public class LockfileMutex : IDisposable {
private readonly string _fileName;
private FileStream? _stream;
public LockfileMutex(string name) {
var assemblyDir = Path.GetDirectoryName(typeof(LockfileMutex).Assembly.Location) ?? throw new FileNotFoundException("cannot determine assembly location");
var file = Path.GetFullPath(Path.Combine(assemblyDir, name));
_fileName = file;
}
public bool Acquire() {
try {
_stream = new FileStream(_fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
return true;
} catch (IOException ex) when (ex.Message.Contains(_fileName)) {
return false;
}
}
public void Dispose() {
if (_stream != null) {
_stream.Dispose();
try {
File.Delete(_fileName);
} catch {
// ignored
}
}
GC.SuppressFinalize(this);
}
}
usage:
using (var mutex = new LockfileMutex("MyMutex")) {
if (mutex.Acquire()) {
Console.WriteLine("acquired");
} else {
Console.WriteLine("not acquired");
}
Console.WriteLine("press any key to end");
Console.ReadKey();
}
Related
I'm using this code to open an access database :
public partial class Start_Baseet : System.Windows.Forms.Form
{
string MyFile = Environment.CurrentDirectory + "\\Baseet.accde";
Microsoft.Office.Interop.Access.Application AccApp = new Microsoft.Office.Interop.Access.Application();
public Start_Baseet()
{
InitializeComponent();
}
public void OpenDb()
{
AccApp.Visible = true;
AccApp.OpenCurrentDatabase(MyFile, false, "017014a");
AccApp.RunCommand(AcCommand.acCmdAppMaximize);
// AccApp.Activate();
}
}
private void Start_Basset_Load(object sender, EventArgs e)
{
try
{
OpenDb();
}
catch
{
AccApp.Quit();
MessageBox.Show("Something is missing", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
finally
{
this.Close();
System.Windows.Forms.Application.Exit();
System.Windows.Forms.Application.ExitThread();
// Process.GetCurrentProcess().CloseMainWindow();
}
The problem is the MSACCESS process is piling up in the running processes so I tried this :
//var prc = Process.GetProcessesByName("MSACCESS.EXE*32");
var prc = Process.GetProcessesByName("Microsoft Access");
if (prc.Length > 0)
{
MessageBox.Show("Access Found");
SetForegroundWindow(prc[0].MainWindowHandle);
}
else
{
AccApp.Visible = true;
AccApp.OpenCurrentDatabase(MyFile, false, "017014a");
AccApp.RunCommand(AcCommand.acCmdAppMaximize);
// AccApp.Activate();
}
}
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
But still with every time I use the code another MSACCESS process starts.
How can I fix this ?
Other point if I ran my app second time it will open a new instance of the same database can I activate the database if it is opened otherwise open a new instance of it ?
Thanks
Try this. This should catch users closing out Access as well through error catching. I'm sure it can be improved on but, I don't get a bunch of MSAccess.exe in the background from this code I wrote a while ago.
public partial class Form1 : Form
{
Microsoft.Office.Interop.Access.Application accApp = new Microsoft.Office.Interop.Access.Application();
private bool isFormClosed = false;
public Form1()
{
InitializeComponent();
OpenMicrosoftAccessFile(#"FileName");
Thread t = new Thread(new ThreadStart(CheckIfMSAccessExeIsRunning));
t.Start();
}
/// <summary>
/// The User Closed Out Access Cleanup.
/// </summary>
public void CheckIfMSAccessExeIsRunning()
{
int secondsToWait = 5*1000;
while(!isFormClosed)
{
if (accApp != null &&
accApp.Visible == false)
CloseMicrosoftAccessFile();
Thread.Sleep(secondsToWait);
}
CloseMicrosoftAccessFile();
}
private bool OpenMicrosoftAccessFile(string accessFileName)
{
try
{
if (accApp != null &&
!accApp.Visible)
{
CloseMicrosoftAccessFile();
}
if (accApp == null)
{
accApp = new Microsoft.Office.Interop.Access.Application();
accApp.OpenCurrentDatabase(accessFileName);
accApp.Visible = true;
}
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine((ex.InnerException != null) ? ex.InnerException : "");
CloseMicrosoftAccessFile();
return false;
}
}
private void CloseMicrosoftAccessFile()
{
try
{
if (accApp != null)
{
accApp.CloseCurrentDatabase();
accApp.Quit();
}
}
catch (Exception ex)
{
//Good chance there never was an Access exe.
Console.WriteLine(ex.Message);
Console.WriteLine((ex.InnerException != null) ? ex.InnerException : "");
}
finally
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(accApp);
accApp = null;
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
isFormClosed = true;
}
}
Also, if you still have processes running the Debugger or Visual Studio is probably holding onto it still. It would be good to test this from the release exe. If OpenMicrosoftAccessFile returns false you can try opening it up again but, this way ignores the error it caught.
I have a .NET Core 3.1 Windows application (WinForm app) running on Windows 10 Version 10.0.17134 Build 17134. I am trying to connect and pair with Bluetooth devices using BluetoothLEAdvertisementWatcher. In the main form of the app I am using CefSharp.WinForms to display an HTML page.
My problem is that when I initialize the browser using _browser = new ChromiumWebBrowser(Settings.Default.IndexPageUrl); I can no longer pair with the Bluetooth device. I get AccessDenied returned from pairRequest.Status in my custom pairing event.
Here is the code:
using CefSharp;
using CefSharp.WinForms;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Enumeration;
namespace myApp
{
public partial class MainForm : Form
{
private readonly ILogger<MainForm> _logger;
private ChromiumWebBrowser _browser;
private static BluetoothLEAdvertisementWatcher _bleAdvertisementWatcher = null;
private static volatile ConcurrentDictionary<ulong,BleDeviceInfo> _bleDevicesInfo;
private readonly SemaphoreSlim _semaphoreSlim;
/// <summary>
/// Used to create a thread-safe boolean; do not access directly use AddingDevices instead
/// </summary>
private int _addingDevicesBool = 0;
public event Action<BleDeviceInfo> OnBleDeviceDetected;
public MainForm(): this(Program.LogFactory.CreateLogger<MainForm>())
{ }
public MainForm(ILogger<MainForm> logger)
{
_logger = logger;
_semaphoreSlim = new SemaphoreSlim(1, 1);
_bleDevicesInfo = new ConcurrentDictionary<ulong,BleDeviceInfo>();
InitBluetoothUtils();
InitializeBrowser();
}
#region browser setup
private void InitializeBrowser()
{
try
{
Cef.EnableHighDPISupport();
//When I comment out the 2 lines below I can succesfully pair with a BLE device
_browser = new ChromiumWebBrowser(Settings.Default.IndexPageUrl);
toolStripContainer.ContentPanel.Controls.Add(_browser);
//TODO: Uncomment the lines below to see Chrome Dev Tools
//#if DEBUG
// _browser.IsBrowserInitializedChanged += OnIsBrowserInitializedChanged;
//#endif
}
catch (Exception ex)
{
_logger.LogError(ex, Settings.BrowserInitError);
throw;
}
}
private void OnIsBrowserInitializedChanged(object sender, EventArgs e)
{
_browser.ShowDevTools();
}
#endregion
#region BLE setup
#region properties
/// <summary>
/// Thread-safe boolean property
/// </summary>
public bool ListeningForBleDevices
{
get { return (Interlocked.CompareExchange(ref _addingDevicesBool, 1, 1) == 1); }
set
{
if (value)
{
Interlocked.CompareExchange(ref _addingDevicesBool, 1, 0);
}
else
{
Interlocked.CompareExchange(ref _addingDevicesBool, 0, 1);
}
}
}
#endregion
private void InitBluetoothUtils()
{
StartListeningForBleDevices();
}
public void StartListeningForBleDevices()
{
ListeningForBleDevices = true;
StartBleWatcher();
}
private void StartBleWatcher()
{
try
{
ListeningForBleDevices = false;
if(_bleAdvertisementWatcher == null)
{
_bleAdvertisementWatcher = new BluetoothLEAdvertisementWatcher
{
ScanningMode = BluetoothLEScanningMode.Active
};
// Only activate the watcher when we're recieving values >= -80
_bleAdvertisementWatcher.SignalStrengthFilter.InRangeThresholdInDBm = -80;
// Stop watching if the value drops below -90 (user walked away)
_bleAdvertisementWatcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -90;
// Register events
_bleAdvertisementWatcher.Received += OnBleAdvWatcherReceived;
_bleAdvertisementWatcher.Stopped += OnBleAdvWatcherStopped;
// Wait 5 seconds to make sure the device is really out of range
_bleAdvertisementWatcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(5000);
_bleAdvertisementWatcher.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(2000);
}
//Start Watcher
ListeningForBleDevices = true;
_bleAdvertisementWatcher.Start();
}
catch (Exception ex)
{
_logger.LogError(ex, string.Empty);
throw;
}
}
public void StopBleWatcher()
{
_bleAdvertisementWatcher?.Stop();
ListeningForBleDevices = false;
}
private void OnBleAdvWatcherStopped(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementWatcherStoppedEventArgs args)
{
_logger.LogInformation("Ble Advertisement Watcher stopped");
}
/// <summary>
/// This event will fire multiple times for the same BLE device
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private async void OnBleAdvWatcherReceived(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
{
if(!ListeningForBleDevices)
{
return;
}
BleDeviceInfo bleDeviceInfo = null;
try
{
var advLocalName = args.Advertisement.LocalName;
if (string.IsNullOrEmpty(advLocalName) || !advLocalName.Contains("my custom prefix", StringComparison.OrdinalIgnoreCase))
{
return;
}
_semaphoreSlim.Wait();
bleDeviceInfo = await SetBleDeviceInfo(args).ConfigureAwait(false);
_semaphoreSlim.Release();
}
catch (Exception ex)
{
_logger.LogError(ex, string.Empty);
_semaphoreSlim.Release();
throw;
}
if(bleDeviceInfo != null)
{
OnBleDeviceDetected?.Invoke(bleDeviceInfo);
}
}
private async Task<BleDeviceInfo> SetBleDeviceInfo(BluetoothLEAdvertisementReceivedEventArgs args)
{
BleDeviceInfo bleDeviceInfo = null;
try
{
var bluetoothAddress = args.BluetoothAddress;
var deviceExists = GetBleDevice(bluetoothAddress);
if(deviceExists == null)
{
BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(bluetoothAddress);
//TODO: Pairing will not work when ChromiumWebBrowser gets initialized
var isPaired = await PairDevice(bleDevice).ConfigureAwait(false);
bleDeviceInfo = new BleDeviceInfo(bleDevice, args);
_bleDevicesInfo.AddOrUpdate(bleDeviceInfo.BluetoothAddress, bleDeviceInfo, (key, bleDeviceInfo) => bleDeviceInfo);
}
}
catch (Exception ex)
{
_logger.LogError(ex, string.Empty);
throw;
}
return bleDeviceInfo;
}
public BleDeviceInfo GetBleDevice(ulong bluetoothAddress)
{
try
{
return _bleDevicesInfo.Values.FirstOrDefault(d => d.BluetoothAddress.Equals(bluetoothAddress));
}
catch (Exception ex)
{
_logger.LogError(ex, string.Empty);
throw;
}
}
public async Task<bool> PairDevice(BluetoothLEDevice bleDevice)
{
if (bleDevice == null)
{
return false;
}
var isPaired = false; // bleDevice.DeviceInformation.Pairing.IsPaired;
try
{
var canPair = bleDevice.DeviceInformation.Pairing.CanPair;
var deviceId = bleDevice.DeviceId;
if (canPair)
{
DeviceInformationCustomPairing customPairing = bleDevice.DeviceInformation.Pairing.Custom;
customPairing.PairingRequested += OnCustomPairingRequested;
var pairRequest = await customPairing.PairAsync(DevicePairingKinds.ProvidePin, DevicePairingProtectionLevel.None);
customPairing.PairingRequested -= OnCustomPairingRequested;
var resultStatus = pairRequest.Status;
isPaired = resultStatus == DevicePairingResultStatus.Paired;
if (isPaired)
{
//TODO: Verify this code block
bleDevice.Dispose();
Thread.Sleep(2000); //try 2 second delay.
//Reload device so that the GATT services are there. This is why we wait.
bleDevice = await BluetoothLEDevice.FromIdAsync(deviceId);
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, string.Empty);
throw;
}
return isPaired;
}
public async Task<bool> PairDevice(ulong bluetoothAddress)
{
BluetoothLEDevice bleDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(bluetoothAddress, BluetoothAddressType.Public);
return await PairDevice(bleDevice).ConfigureAwait(false);
}
private void OnCustomPairingRequested(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args)
{
try
{
//This method does not get called when ChromiumWebBrowser is initialized
//However, when _browser = new ChromiumWebBrowser is not called this method works as expected
var deviceName = args.DeviceInformation.Name;
var devicePin = GetBlePin(deviceName);
var pinDeferral = args.GetDeferral();
args.Accept(devicePin.ToString(CultureInfo.InvariantCulture));
pinDeferral.Complete();
}
catch (Exception)
{
throw;
}
}
private int GetBlePin(string serialNumber)
{
return 12345;
}
#endregion
}
}
Things I have tried:
Calling InitializeBrowser on a separate thread using Task.Run(() => { InitializeBrowser(); }).ConfigureAwait(false);
Calling InitBluetoothUtils on a separate thread using Task.Run(() => { InitBluetoothUtils(); }).ConfigureAwait(false);
Calling both InitializeBrowser and InitBluetoothUtils on separate threads
Tried using SynchronizationContext by getting the current context in the MainForm constructor, and then calling PairDevice(bleDevice) using that context
Each time I get AccessDenied. The only thing that works successfully is when I comment out _browser = new ChromiumWebBrowser(BASettings.Default.IndexPageUrl); and toolStripContainer.ContentPanel.Controls.Add(_browser);
Here is my code
I tried in Debug Mode. It works.
While in release does not why? Its a WPF application
This piece of code i put in Main Method for checking if a application is running or not. I want single instance to be running only. I copied this code from Stack Overflow only.
[STAThread]
static void Main()
{
const string MutexName = "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}";
try
{
Mutex mutex = new Mutex(true, MutexName);
if (mutex.WaitOne(TimeSpan.Zero, true))
{
mutex.ReleaseMutex();
//Here Application logic
}
else
{
MessageBox.Show("Application is alreadey running.");
Environment.Exit(1);
}
}
catch
{
Environment.Exit(1);
}
}
I don't know the exact reason. But this modification works
[STAThread]
static void Main()
{
const string MutexName = "8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F";
try
{
Mutex mutex;
if (!Mutex.TryOpenExisting(MutexName, out mutex))
{
mutex = new Mutex(true,MutexName);
var app = new App();
app.Run();
}
else
{
Environment.Exit(1);
}
}
catch
{
Environment.Exit(1);
}
}
I was using the following code to move a file into a folder
File.Move(Source,Dest);
I then try to open and read the file, in the next method, but I kept getting file locked by process errors.
So I changed the file move to the following code
public async static Task<bool> MoveFileAsync(string sourceFileName, string destinationFileName)
{
using(FileStream sourceStream = File.Open(sourceFileName, FileMode.Open))
{
using(FileStream destinationStream = File.Create(destinationFileName))
{
try
{
await sourceStream.CopyToAsync(destinationStream);
File.Delete(sourceFileName);
return true;
}
catch
{
return false;
}
}
}
}
I keep getting errors that the file locked
Any ideas on how to prevent this from happening.
This is all using a FileSystemWatcher to monitor the folder... the code is below. I can confirm none of these error happen when I drag and drop files into the folders... even when I drag multiple files...
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DocumentManager.RepositoryService
{
internal class MonitorDropFolder
{
public string RepositoryPath { get; set; }
public FileSystemWatcher Watcher { get; set; }
public MonitorDropFolder ()
{
Watcher = new FileSystemWatcher();
Watcher.Path = #"c:\Repository\DropLocation";
Watcher.NotifyFilter = NotifyFilters.FileName;
Watcher.Filter = "*.docx";
Watcher.Created += new FileSystemEventHandler(OnCreatedHandler);
StartMonitoring();
}
public void StartMonitoring()
{
Watcher.EnableRaisingEvents = true;
}
public void StopMonitoring()
{
Watcher.EnableRaisingEvents = false;
}
private void OnCreatedHandler(object source, FileSystemEventArgs e)
{
if(e.ChangeType == WatcherChangeTypes.Created)
{
//don't process temporary files
if (Path.GetFileName(e.FullPath).Substring(0, 1) == "~" || Path.GetFileName(e.FullPath).Substring(0, 1) == "$")
return;
var result = convert(e.FullPath, GetDocStatus(e.Name)).Result;
FileService.MoveNativeToDraft(e.FullPath);
}
}
private async Task<bool> convert(string fileName, string docStatus)
{
try
{
ConvertWordToPDF convertor = new ConvertWordToPDF();
var task = Task.Run(()=>convertor.Convert(fileName, docStatus));
await task;
return true;
}
catch (Exception)
{
return false;
}
}
}
}
Thanks in advance
Update:
I am calling the code like this...
public static void MoveIntoRepository(string sourceFile)
{
string destinationDir = #"C:\Repository\DropLocation\";
var result = MoveFileAsync(sourceFile, Path.Combine(destinationDir, Path.GetFileName(sourceFile))).Result;
}
I also tried getting around the file lock like this...
bool isFileLocked = isLocked(filename);
int numTries = 0;
while(isFileLocked)
{
numTries++;
if (numTries > 100)
throw new Exception("FileLock Error");
///the following is actually in a called method
byte[] byteArray = File.ReadAllBytes(filename);
///... rest of code here
Thread.Sleep(500);
isFileLocked = isLocked(filename);
}
which calls this method
private static bool isLocked(string filename)
{
try
{
FileStream st = new FileStream();
st = File.Open(filename,FileMode.Open);
st.Close();
return false;
}
catch (Exception)
{
return true;
throw;
}
}
See my comments below in code:
using(FileStream sourceStream = File.Open(sourceFileName, FileMode.Open))
{
using(FileStream destinationStream = File.Create(destinationFileName))
{
try
{
await sourceStream.CopyToAsync(destinationStream);
// The sourceFileName file is locked since you are inside the
// the using statement. Move statement for deleting file to
// outside the using.
File.Delete(sourceFileName);
return true;
}
catch
{
return false;
}
}
}
// Move it here
I've created a user control (windows form application) to get an instance of Word (either active or new), and provide a button to open documents into that instance using a file dialog picker.
The form contains 2 buttons, 1 for getting the word instance and another for opening a document. It also contains a list box for displaying the open documents, and an openfiledialog control to provide the means for selecting documents to open.
I am handling the Application.DocumentOpen event in order to populate the listbox...
m_wordApp.DocumentOpen += new msoWord.ApplicationEvents4_DocumentOpenEventHandler(m_wordApp_DocumentOpen);
I am determining when i need to reinvoke my method that populates the listbox to ensure that access to the control is on the same thread that created it....
private void AddDocument(string name)
{
try
{
if (m_documentsListBox.InvokeRequired && m_documentsListBox.IsHandleCreated&&!m_documentsListBox.IsDisposed)
{
this.Invoke(m_AddDocument, new object[] { name });
return;
}
if (!m_documentsListBox.Items.Contains(name))
m_documentsListBox.Items.Add(name);
}
catch (Exception ex)
{
}
}
Im not using 2 dots, and i believe i am releasing any COM objects correctly.
Why does the application hang on either the line of code that opens the document ...
WordDoc = m_wordDocs.Open(ref fileName);
or the line that reinvokes the AddDocument() method...
this.Invoke(m_AddDocument, new object[] { name });
somewhere along the line i think i must be having a thread issue, because the hang only happens if i choose to open a document using the button, rather than from within the Word application directly.
full code below...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
// use these for the core office & word references
using msoWord = Microsoft.Office.Interop.Word;
namespace MCDevNET.Office.Word.TestUIControls
{
public partial class OpenWordDocument : Form
{
public OpenWordDocument()
{
InitializeComponent();
m_openWordButton.Click += new EventHandler(buttonOpenWordApp_Click);
m_openDocumentButton.Click += new EventHandler(buttonOpenDocument_Click);
m_AddDocument = new UpdateListControl(AddDocument);
}
#region Form: control eventHandlers
void buttonOpenWordApp_Click(object sender, EventArgs e)
{
try
{
if (!IsValid(m_wordApp))
WordApp = GetInstance();
AddAllDocuments();
}
catch (Exception ex)
{
}
}
void buttonOpenDocument_Click(object sender, EventArgs e)
{
OpenWordDoc();
}
public delegate void UpdateListControl(string name);
private UpdateListControl m_AddDocument;
private void AddDocument(string name)
{
try
{
if (m_documentsListBox.InvokeRequired && m_documentsListBox.IsHandleCreated&&!m_documentsListBox.IsDisposed)
{
this.Invoke(m_AddDocument, new object[] { name });
return;
}
if (!m_documentsListBox.Items.Contains(name))
m_documentsListBox.Items.Add(name);
}
catch (Exception ex)
{
}
}
private void AddAllDocuments()
{
try
{
m_documentsListBox.Items.Clear();
if (m_wordDocs != null)
{
for (int i = 1; i <= m_wordDocs.Count; i++)
AddDocument(m_wordDocs[i].Name);
}
}
catch (Exception ex)
{
}
}
#endregion
#region Word: properties & eventhandlers
private msoWord.Document m_wordDoc;
public msoWord.Document WordDoc
{
get { return m_wordDoc; }
private set
{
try
{
if (m_wordDoc != value)
{
ReleaseCOMObject(m_wordDoc);
m_wordDoc = value;
}
}
catch (Exception ex)
{
}
}
}
private msoWord.Documents m_wordDocs;
public msoWord.Documents WordDocs
{
get { return m_wordDocs; }
private set
{
try
{
if (m_wordDocs != value)
{
ReleaseCOMObject(m_wordDocs);
m_wordDocs = value;
}
}
catch (Exception ex)
{
}
}
}
private msoWord.Application m_wordApp;
public msoWord.Application WordApp
{
get { return m_wordApp; }
set
{
try
{
if (m_wordApp != value)
{
if (m_wordApp != null)
{
m_wordApp.DocumentOpen -= new msoWord.ApplicationEvents4_DocumentOpenEventHandler(m_wordApp_DocumentOpen);
ReleaseCOMObject(m_wordApp);
}
m_wordApp = value;
if (IsValid(m_wordApp))
{
m_wordApp.DocumentOpen += new msoWord.ApplicationEvents4_DocumentOpenEventHandler(m_wordApp_DocumentOpen);
WordDocs = m_wordApp.Documents;
}
}
}
catch (Exception ex)
{
}
}
}
void m_wordApp_DocumentOpen(msoWord.Document doc)
{
try
{
string name = doc.Name;
AddDocument(name);
}
catch (Exception ex)
{
}
finally
{
ReleaseCOMObject(doc);
doc = null;
}
}
private msoWord.Application GetInstance()
{
msoWord.Application app = null;
try
{
app = (msoWord.Application)Marshal.GetActiveObject("Word.Application");
}
catch (Exception ex)
{
if (app == null)
app = new msoWord.Application();
}
finally
{
if (IsValid(app))
{
app.Visible = true;
app.Activate();
}
}
return app;
}
private void OpenWordDoc()
{
try
{
m_openFileDialog.AddExtension = true;
m_openFileDialog.Filter = "All Word (*.docx; *.docm; *.doc; *.dotx; *.dotm; *.dot)|*.docx;*.docm;*.doc;*.dotx;*.dotm;*.dot|Word Documents (*.docx)|*.docx|Word Macro-Enabled Documents (*.docm)|*.docm|Word 97-2003 Documents (*.doc)|*.doc|All Word Templates (*.dotx; *.dotm; *.dot)|*.dotx;*.dotm;*.dot|Word Templates (*.dotx)|*.dotx|Word Macro-Enabled Templates (*.dotm)|*.dotm)";
m_openFileDialog.FilterIndex = 1;
m_openFileDialog.Multiselect = false;
m_openFileDialog.Title = "Open Word Document";
if (m_openFileDialog.ShowDialog() == DialogResult.OK)
{
object fileName = m_openFileDialog.FileName;
WordDoc = m_wordDocs.Open(ref fileName);
}
}
catch (Exception ex)
{
}
}
private bool IsValid(msoWord.Application app)
{
try
{
if (app != null)
{
string name = app.Caption;
return true;
}
}
catch (Exception ex)
{
}
return false;
}
#endregion
private void ReleaseCOMObject(object comObject)
{
try
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
if (comObject != null && Marshal.IsComObject(comObject))
Marshal.ReleaseComObject(comObject);
}
catch (Exception ex)
{
}
}
}
}
namespace MCDevNET.Office.Word.TestUIControls
{
partial class OpenWordDocument
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.m_documentsListBox = new System.Windows.Forms.ListBox();
this.m_openDocumentButton = new System.Windows.Forms.Button();
this.m_openWordButton = new System.Windows.Forms.Button();
this.m_openFileDialog = new System.Windows.Forms.OpenFileDialog();
this.SuspendLayout();
//
// lb_Documents
//
this.m_documentsListBox.FormattingEnabled = true;
this.m_documentsListBox.Location = new System.Drawing.Point(12, 41);
this.m_documentsListBox.Name = "lb_Documents";
this.m_documentsListBox.Size = new System.Drawing.Size(156, 134);
this.m_documentsListBox.TabIndex = 8;
//
// m_openDocumentButton
//
this.m_openDocumentButton.Location = new System.Drawing.Point(93, 12);
this.m_openDocumentButton.Name = "m_openDocumentButton";
this.m_openDocumentButton.Size = new System.Drawing.Size(75, 23);
this.m_openDocumentButton.TabIndex = 7;
this.m_openDocumentButton.Text = "Doc";
this.m_openDocumentButton.UseVisualStyleBackColor = true;
//
// m_openWordButton
//
this.m_openWordButton.Location = new System.Drawing.Point(12, 12);
this.m_openWordButton.Name = "m_openWordButton";
this.m_openWordButton.Size = new System.Drawing.Size(75, 23);
this.m_openWordButton.TabIndex = 6;
this.m_openWordButton.Text = "Word";
this.m_openWordButton.UseVisualStyleBackColor = true;
//
// m_openFileDialog
//
this.m_openFileDialog.FileName = "openFileDialog1";
//
// OpenWordDocument
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(182, 184);
this.Controls.Add(this.m_documentsListBox);
this.Controls.Add(this.m_openDocumentButton);
this.Controls.Add(this.m_openWordButton);
this.Name = "OpenWordDocument";
this.Text = "OpenWordDocument";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ListBox m_documentsListBox;
private System.Windows.Forms.Button m_openDocumentButton;
private System.Windows.Forms.Button m_openWordButton;
private System.Windows.Forms.OpenFileDialog m_openFileDialog;
}
}
The hang happens on the call to Documents.Open(fileName)
You have an event handler wired up for the Application.DocumentOpen event. On removing this event handler the hang no longer occurs.
I presume the reason for the problem is that you are getting deadlocked as Word tries to fire that event before the Documents.Open call returns. Meaning the thread that handles the event is still busy.
Replacing
WordDoc = m_wordDocs.Open(ref fileName)
with
new System.Threading.Tasks.Task(() => WordDoc = m_wordDocs.Open(ref fileName))
.Start();
To open the document on a different thread seems to resolve the issue.