We have an UWP application and we would like to have the following scenario:
open Microsoft word from it with a document
edit document
close document and get data to our application.
We have an Silverlight application that uses the code below and resolves the problem nicely. Can we do something similar in UWP? Programmatically open Word and wait for instance closing.
private void SetupWordInstance(bool visible = true)
{
if (AutomationFactory.IsAvailable)
{
_wordApp = null;
try
{
_wordApp = AutomationFactory.CreateObject("Word.Application");
_wordVersion = _wordApp.Version;
}
catch
{
try
{
_wordApp = AutomationFactory.CreateObject("Word.Application");
_wordVersion = _wordApp.Version;
}
catch (Exception)
{
Utils.ShowMessage(Resource.MissingWordApplicationErrorMessage);
}
}
if (_wordApp != null)
{
AutomationEvent beforeCloseEvent = AutomationFactory.GetEvent(_wordApp, "DocumentBeforeClose");
beforeCloseEvent.AddEventHandler(new BeforeCloseAppDelegate(BeforeCloseApp));
AutomationEvent quitEvent = AutomationFactory.GetEvent(_wordApp, "Quit");
quitEvent.AddEventHandler(new QuitAppDelegate(QuitApp));
if (visible)
{
_wordApp.Visible = true;
_wordApp.Activate();
FocusWordInstance();
}
}
}
else
{
Utils.ShowMessage(Resource.MissingAutomationErrorMessage);
}
}
There is a possibility that it can correspond by the technology called desktop bridge which Microsoft provides. Here's an explanation. Easily, it is to extract the Windows Desktop function not available in UWP and provide it together with application.
Docs/Windows/UWP/Develop/Porting apps to Windows 10/Desktop Bridge
The following is a sample when using Excel.
Desktop app bridge to UWP Samples
UWP calling Office Interop APIs
Windows Application Packaging Project Samples
Excel.Interop
Since the definition of Word API is below, it seems that it can be used as above.
Microsoft.Office.Interop.Word Namespace
Related
I am pretty new in WindowsPhone applications development. I am currently developing a Unity application for Windows Phone 8.0. Inside this app I would like to open a PDF using the appropriate application on the phone (Acrobat Reader, Windows Reader, etc...)
First, I tried this :
void PDFButtonToggled(bool i_info)
{
Dispatcher.BeginInvoke(() =>
{
DefaultLaunch();
});
}
async void DefaultLaunch()
{
// Path to the file in the app package to launch
string PDFFilePath = #"Data/StreamingAssets/ImageTest.jpg";
var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(PDFFilePath);
if (file != null)
{
// Set the option to show the picker
var options = new Windows.System.LauncherOptions();
options.DisplayApplicationPicker = true;
// Launch the retrieved file
bool success = await Windows.System.Launcher.LaunchFileAsync(file, options);
if (success)
{
// File launched
}
else
{
throw new Exception("File launch failed");
}
}
else
{
throw new Exception("Could not find file");
}
}
It returned me an exception so I searched why. I found that topic (written in 2013 :/) about async functions / threads : LINK. To sumarize, here the answer of Unity staff :
It will only work on Windows Store Apps, and you'll have to wrap the code in #if NET_FX/#endif. On other platforms, you cannot use async/.NET 4.5 code in scripts. If you want to use it for windows phone, you'll have to write that code in separate visual studio solution and compile it to DLL, so unity can use it as a plugin.
So I decided to create the double DLL solution described in the Unity Manual here : LINK. But when I complete the class of the first DLL with the "async void DefaultLaunch()" function given above I don't have references about Windows.ApplicationModel.etc... and Windows.System.etc... .
And here I am, a little bit lost between WP, Unity, 8.0 apps, StoreApps, etc...
If anyone has advices, questions, anything that can help me, it's welcome. :)
Crèvecoeur
I found a solution by myself but on a WindowsPhone8.1 application.
Here it is :
async void PDFButtonToggled(bool i_info)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
DefaultLaunchFile();
});
}
async void DefaultLaunchFile()
{
StorageFolder dataFolder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Data");
StorageFolder streamingAssetsFolder = await dataFolder.GetFolderAsync("StreamingAssets");
// Path to the file in the app package to launch
string filePath = "PDFTest.pdf";
var file = await streamingAssetsFolder.GetFileAsync(filePath);
if (file != null)
{
// Launch the retrieved file
bool success = await Windows.System.Launcher.LaunchFileAsync(file);
if (success)
{
// File launched
}
else
{
throw new Exception("File launch failed");
}
}
else
{
throw new Exception("File not found");
}
}
I've developed a free UWP app with IAP included.
I developed this app for Windows 10 Mobile. I published an IAP to the store named customBackground, and published my app as well as the IAP to the store.
After both of them has published, I downloaded my published app from the store and try to buy the IAP.
However it returned an system popup saying "This in-app item is no longer availble in MY-APP-NAME". I don't know why this happened.
There are problems:
When I was trying in debug mode in visual studio using CurrentAppSimulator class, it doesn't popup the purchase state selection on my phone or emulator, but it pops up on desktop version. it only reads the stored state in WindowsStoreProxy.xml.
I've also tried using CurrentApp class in debug/release mode after the IAP is published, but no luck, it returns the same error as the store version.
internet permission in Package.appxmanifest is enabled.
Here's the code in my released app in the store:
private async void buy_Click(object sender, RoutedEventArgs e)
{
LicenseInformation licenseInformation = CurrentApp.LicenseInformation;
if (!licenseInformation.ProductLicenses["customBackground"].IsActive)
{
Debug.WriteLine("Buying this feature...");
try
{
await CurrentApp.RequestProductPurchaseAsync("customBackground");
if (licenseInformation.ProductLicenses["customBackground"].IsActive)
{
var purchaseStat = LocalizedStrings.GetString(LocalizedStringEnum.havePurchased);
var b = new MessageDialog(purchaseStat);
b.ShowAsync();
Debug.WriteLine("You bought this feature.");
isIAPValid = true;
}
else
{
var purchaseStat = LocalizedStrings.GetString(LocalizedStringEnum.notPurchased);
var b = new MessageDialog(purchaseStat);
b.ShowAsync();
Debug.WriteLine("this feature was not purchased.");
}
}
catch (Exception)
{
var purchaseStat = LocalizedStrings.GetString(LocalizedStringEnum.purchaseFailed);
var b = new MessageDialog(purchaseStat);
b.ShowAsync();
Debug.WriteLine("Unable to buy this feature.");
}
}
else
{
var purchaseStat = LocalizedStrings.GetString(LocalizedStringEnum.alreadyOwned);
var b = new MessageDialog(purchaseStat);
b.ShowAsync();
Debug.WriteLine("You already own this feature.");
isIAPValid = true;
}
}
Thanks!
Later after one day, I found my iap is working.
Seems like a temporary problem, Microsoft does need to improve their store system.
I have the following function which opens a dxf file in an Autocad Exe, by zooming a specific coordinate via my C# desktop application.
public static void zoomDrwaing(String drawingFile, String lotId)
{
AcadApplication acadApp = null;
AcadDocument doc = null;
double[] coordinates = new double[3];
String errorMessage = "";
try
{
coordinates = ReadCoordinates(drawingFile, lotId); // done via netDxf api
acadApp = new Autodesk.AutoCAD.Interop.AcadApplication();
acadApp.Visible = true;
doc = acadApp.Documents.Open(drawingFile, true);
double[] points = new double[3] { coordinates[0], coordinates[1], coordinates[2] };
acadApp.ZoomCenter(points, 30);
}
catch (Exception ex)
{
errorMessage = ex.ToString();
}
finally
{
if (acadApp != null) Marshal.FinalReleaseComObject(acadApp);
}
}
I would like to know whether there is any possibility of loading the Autocad Exe (with the zoomed dxf file) inside one of the Windows forms in my desktop application it-self rather than opening the exe separately.
I haven't tried it but apparently you can use the ActiveX control from DWG Trueview Here is a forum post on the Autodesk forum with some sample code. Googling DWG Trueview Activex should generate some reading material. Or you may just read this and abandon all hope. The $$ alternative is RealDwg or Open Design. Read the AutoCAD Tag wiki for more resources and info on that.
Because Autodesk love to destroy their inbound links from time to time, you should be able to land on the first topic I mentioned using Google if they kill it again. Don't get me started on that.
I am using visual studio 2010 and I am having a .DWG file which I want to open in autocad. Till now I have used this.
Process p = new Process();
ProcessStartInfo s = new ProcessStartInfo("D:/Test File/" + fileName);
p.StartInfo = s;
p.Start();
But what I want is to close the file inside the Autocad but not the autocad itself. (Means atocad.exe should be kept running).
Till now I hve used this but its closing the acad.exe not the file.
foreach (Process Proc in Process.GetProcesses())
{
if (Proc.ProcessName.Equals("acad"))
{
Proc.CloseMainWindow();
Proc.Kill();
}
}
Take the Autocad .NET libraries from Autodesk Sites (http://usa.autodesk.com/adsk/servlet/index?id=773204&siteID=123112)
Then you will be able to use Application and Document classes.
They will give you full control over opening and closing documents within the application.
You can find many articles on that, and can ask further questions.
AutoCAD does have an api. there are 4 assemblys. Two for in-process and two for COM.
inprocess :
acdbmgd.dll
acmgd.dll
COMInterop :
Autodesk.Autocad.Interop.dll
Autodesk.Autocad.Interop.Common.dll
this is a method that will open a new instance of AutoCAD or it will connect to an existing running instance of AutoCAD.
you will need to load these .dlls into your project references.
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
namespace YourNameSpace {
public class YourClass {
AcadApplication AcApp;
private const string progID = "AutoCAD.Application.18.2";// this is AutoCAD 2012 program id
private string profileName = "<<Unnamed Profile>>";
private const string acadPath = #"C:\Program Files\Autodesk\AutoCAD 2012 - English\acad.exe";
public void GetAcApp()
{
try
{
AcApp = (AcadApplication)Marshal.GetActiveObject(progID);
} catch {
try {
var acadProcess = new Process();
acadProcess.StartInfo.Arguments = string.Format("/nologo /p \"{0}\"", profileName);
acadProcess.StartInfo.FileName = (#acadPath);
acadProcess.Start();
while(AcApp == null)
{
try { AcApp = (AcadApplication)Marshal.GetActiveObject(progID); }
catch { }
}
} catch(COMException) {
MessageBox.Show(String.Format("Cannot create object of type \"{0}\"",progID));
}
}
try {
int i = 0;
var appState = AcApp.GetAcadState();
while (!appState.IsQuiescent)
{
if(i == 120)
{
Application.Exit();
}
// Wait .25s
Thread.Sleep(250);
i++;
}
if(AcApp != null){
// set visibility
AcApp.Visible = true;
}
} catch (COMException err) {
if(err.ErrorCode.ToString() == "-2147417846"){
Thread.Sleep(5000);
}
}
}
}
}
closeing it is as simple as
Application.Exit();
and forgive the code. its atrocious, this was one of my first methods when i just started developing...
I doubt you will be able to do this unless AutoCAD has an API that you can hook into and ask it to close the file for you.
Your c# app can only do things to the process (acad.exe) , it doesn't have access to the internal operations of that process.
Also, you shouldn't use Kill unless the process has become unresponsive and certainly not immediately after CloseMainWindow.
CloseMainWindow is the polite way to ask an application to close itself. Kill is like pulling the power lead from the socket. You aren't giving it the chance to clean up after itself and exit cleanly.
There is one other possibility - this will only work if your C# code is running on the same machine as the AutoCAD process and it is not really recommended, but, if you are really stuck and are prepared to put up with the hassle of window switching you can send key strokes to an application using the SendKeys command.
MSDN articles here:
http://msdn.microsoft.com/EN-US/library/ms171548(v=VS.110,d=hv.2).aspx
http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send.aspx
Using this you could send the key strokes to simulate the user using the menu commands to close the file.
To perform the closing of file, best way out is to follow the steps at this ObjectARX SDK for c# and change the following code with the below code.
[CommandMethod("CD", CommandFlags.Session)]
static public void CloseDocuments()
{
DocumentCollection docs = Application.DocumentManager;
foreach (Document doc in docs)
{
// First cancel any running command
if (doc.CommandInProgress != "" &&
doc.CommandInProgress != "CD")
{
AcadDocument oDoc =
(AcadDocument)doc.AcadDocument;
oDoc.SendCommand("\x03\x03");
}
if (doc.IsReadOnly)
{
doc.CloseAndDiscard();
}
else
{
// Activate the document, so we can check DBMOD
if (docs.MdiActiveDocument != doc)
{
docs.MdiActiveDocument = doc;
}
int isModified =
System.Convert.ToInt32(
Application.GetSystemVariable("DBMOD")
);
// No need to save if not modified
if (isModified == 0)
{
doc.CloseAndDiscard();
}
else
{
// This may create documents in strange places
doc.CloseAndSave(doc.Name);
}
}
}
I try to write a auto answer machin with TAPI in C#.NET.
I using tapi3_dev sample to work.this sample work in windows XP but in windows 7, everything is normal(no error or exception) but no sound playback just i can record the audio;
please help me.
my code::
case TAPI3Lib.ADDRESS_EVENT.AE_RINGING: this.PlayVoice(CallInfo);
...
private void PlayVoice(TAPI3Lib.ITCallInfo iTCallInfo)
{
try
{
//the supported file extensions are .avi and .wav. http://msdn.microsoft.com/en-us/library/ms730457.aspx
TAPI3Lib.ITBasicCallControl2 iTBasicCallControl2 = (TAPI3Lib.ITBasicCallControl2)iTCallInfo;
this.selectedTerminal = iTBasicCallControl2.RequestTerminal(TAPI3Lib.TapiConstants.CLSID_String_FilePlaybackTerminal, TAPI3Lib.TapiConstants.TAPIMEDIATYPE_AUDIO, TAPI3Lib.TERMINAL_DIRECTION.TD_CAPTURE);
TAPI3Lib.ITMediaPlayback iTMediaPlayback = (TAPI3Lib.ITMediaPlayback)this.selectedTerminal;
object[] playList = new object[1];
playList[0] = #"C:\ModemLog\7533f717-6cc5-41d5-9845-6983cff85e4b.avi";
//playList[0] = #"C:\Users\Abedi\Desktop\Anghezi.wav";
//playList[0] = #"C:\ProgramData\Venta\VentaFax & Voice 6\Service\greet1.wav";
iTMediaPlayback.PlayList = playList;
iTBasicCallControl2.SelectTerminalOnCall(this.selectedTerminal);
this.iTMediaControl = (TAPI3Lib.ITMediaControl)this.selectedTerminal;
if (iTCallInfo.CallState == TAPI3Lib.CALL_STATE.CS_OFFERING)
iTBasicCallControl2.Answer();
this.iTMediaControl.Start();
(selectedTerminal as TAPI3Lib.ITBasicAudioTerminal).Volume = 0;
}
catch (Exception exception)
{
this.Log(exception.Message, "Exception in PlayVoice");
this.WriteLine(exception.Message);
this.buttonDisconnect_Click(null, EventArgs.Empty);
}
}
Is your code running in a windows service? There is a known issue with audio control from a windows service under windows 7. Currently, I cannot find a work-around other than launcing a windows application to intergate with tapi.