Getting installed printers in .Net Maui - printing

I am trying a to get a list of installed printers in my net maui app targeted for windows.
using System.Drawing.Printing;
namespace MauiApp2;
public partial class MainPage : ContentPage
{
int count = 0;
public MainPage()
{
InitializeComponent();
}
private void OnCounterClicked(object sender, EventArgs e)
{
la.Text = PrinterSettings.InstalledPrinters.Count.ToString();
}
}
I tried adding the system.drawing.common reference to the project.
<ItemGroup>
<Reference Include="System.Drawing.Common">
<HintPath>C:\Program Files (x86)\dotnet\shared\Microsoft.WindowsDesktop.App\6.0.13\System.Drawing.Common.dll</HintPath>
</Reference>
</ItemGroup>
And get a list of installed printers using printersettings.installedprinters.
My project is targeted for windows. Am I doing it wrong? Or is there some other way to do it?
Edit:
I updated the code to the following:
#if WINDOWS
public string GetPrinterNames()
{
try
{
x= PrinterSettings.InstalledPrinters.Count.ToString();
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
}
return x;
}
#endif
Still it crashes and shows this code in app.g.i.cs file:
#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
UnhandledException += (sender, e) =>
{
if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
};
#endif
Edit: system.drawing.printing is not supported for .Net Maui with target .net 7. I got the solution to work for now with target .net 6

Related

How can I download a file from my phone? MediaDevices device.DownloadFile() method throws a Not Implmented exception

I am trying to use the MediaDevices library to download files from my phone. I am able to see the files on my phone, but MediaDevice.DownloadFile() throws a NotImplemented exception. I've got version 1.8.0 of the library. Here is my program:
using System;
using System.Diagnostics;
using System.IO;
using MediaDevices;
namespace ReadPhoneFile
{
class Program
{
static MediaDevice thePhone;
static void Main(string[] args)
{
var devices = MediaDevice.GetDevices();
foreach (MediaDevice device in devices)
{
try
{
thePhone = device;
device.Connect();
DownloadFiles(device, "e:/pictures/Rob's Test Phone/Lightroom");
device.Disconnect();
}
catch
{
// If it can't be read, don't worry.
}
}
Console.WriteLine("Press any key.");
Console.ReadKey();
}
static void DownloadFiles(MediaDevice device, string pcFolder)
{
var lightroomDir = device.GetDirectoryInfo(#"Phone\Android\data\com.adobe.lrmobile\files\carouselDocuments\a6f0275ee0b94c90b3c05f093250d4ef\Originals");
// ProcessLightroomFolder(photoDir, pcFolder, false);
foreach (MediaDirectoryInfo subFolder in lightroomDir.EnumerateDirectories())
{
ProcessLightroomFolder(subFolder, pcFolder, true);
}
}
static void ProcessLightroomFolder(MediaDirectoryInfo folder, string pcFolder, bool createFolder)
{
Console.WriteLine($"Processing folder {folder.Name} into folder {pcFolder}");
string pcSubFolder = $"{pcFolder}/{folder.Name}";
if (createFolder)
{
Directory.CreateDirectory(pcSubFolder);
}
foreach (MediaFileInfo file in folder.EnumerateFiles())
{
ProcessLightroomFile(file, pcSubFolder);
}
foreach (MediaDirectoryInfo subFolder in folder.EnumerateDirectories())
{
ProcessLightroomFolder(subFolder, pcSubFolder, true);
}
}
static void ProcessLightroomFile(MediaFileInfo file, string pcFolder)
{
Console.WriteLine($"Processing Lightroom file {file.Name} into folder {pcFolder}");
DownloadFile(file, pcFolder);
}
static void DownloadFile(MediaFileInfo phoneFile, string destinationFolder)
{
try
{
MemoryStream memoryStream = new System.IO.MemoryStream();
thePhone.DownloadFile(phoneFile.FullName, "c:/misc/downloadedFile.dng");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
there is an issue raised on github to solve this problem (https://github.com/Bassman2/MediaDevices/issues/32). The problem is that you are building your app on top of .NET Core 3.1, and this lib works well on .NET Framework 4.* as they warn when you build your project:
Package 'MediaDevices 1.8.0' was restored using '.NETFramework,Version=v4.6.1, .NETFramework,Version=v4.6.2, .NETFramework,Version=v4.7, .NETFramework,Version=v4.7.1, .NETFramework,Version=v4.7.2, .NETFramework,Version=v4.8' instead of the project target framework '.NETCoreApp,Version=v3.1'. This package may not be fully compatible with your project

Start an Android activity in Xamarin Forms?

I am trying to view a hosted PDF file with the default Android pdf viewer in my App with the following code
var intent = new Intent(Intent.ActionView);
intent.SetDataAndType(Uri.Parse("http://sample/url.pdf"), "application/pdf");
intent.SetFlags(ActivityFlags.ClearTop);
Android.Content.Context.StartActivity(intent);
I have used this code in a Native project, so I know that it works within an Android activity. For Xamarin Forms, is there a way for me to start an Android activity from a content page, and vice versa?
You can use DependencyService to implement this function:
INativePages in PCL:
public interface INativePages
{
void StartActivityInAndroid();
}
Implement the interface in Xamarin.Android:
[assembly: Xamarin.Forms.Dependency(typeof(NativePages))]
namespace PivotView.Droid
{
public class NativePages : INativePages
{
public NativePages()
{
}
public void StartAc()
{
var intent = new Intent(Forms.Context, typeof(YourActivity));
Forms.Context.StartActivity(intent);
}
}
}
Start an Android Activity in PCL :
private void Button_Clicked(object sender, EventArgs e)
{
Xamarin.Forms.DependencyService.Register<INativePages>();
DependencyService.Get<INativePages>().StartAc();
}
Forms.Context is obsolete now.
The workaround is to instantiate the current context in Main activity class of Android project as under:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public static Xamarin.Forms.Platform.Android.FormsAppCompatActivity Instance { get; private set; }
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
Instance = this;
}
And retrieve the local context in your NativePages StartAc() method as under:
public void StartAc()
{
var intent = new Intent(MainActivity.Instance, typeof(YourActivity));
MainActivity.Instance.StartActivity(intent);
}
Create an class for this function in an android project:
public class PdfLauncher : IPdfLauncher
{
public void LaunchPdf(string url)
{
//implementation
}
}
Create an interface in a portable project
public interface IPdfLauncher
{
void LaunchPdf(string url);
}
Add a property to your viewmodel so you can call the function from your portable project
public IPdfLauncher PdfLauncher {get;set;}
Add the interface to your viewmodel constructor and pass in an instance that you create in your android main activity. You can now call android code from your xforms commands and, if you ever add iOS or UWP you can simply implement that interface in those projects and pass them in at runtime. I use an injection framework from MVVM to automate creating these platform specific implementations, and I'd recommend you look into it if you find yourself doing these often.

Manual Elmah Logging dosnt work properly in MVC

I used ELAMH 1.2 to log errors in MVC 5. It work well for 404 500... HTTP errors and in controller's catch blocks.
public ActionResult Index()
{
Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception("test"));
try
{
var a = 0;
var b = 1 / a;
}
catch(Exception e)
{
Elmah.ErrorSignal.FromCurrentContext().Raise(e);
}
return View();
}
i get two log for this code.
but it dosent work in a static class like below. i dont get any exception while running ErrorSignal.FromCurrentContext().Raise(e);.
public static class FileUtility
{
public static string SaveSampleFile(HttpPostedFileBase file)
{
try
{
var b = 0;
var a = 1/b;
}
catch (Exception e)
{
ErrorSignal.FromCurrentContext().Raise(e);
return null;
}
}
}
no error log nothing happen!
I have also seen this problem when calling ELMAH logger without any HttpContext in class library projects.
I used the old manual way to get around this:
Elmah.ErrorLog.GetDefault(null).Log(new Error(ex));

PowerDesigner addin develop

Anyone knows how to develop an add-in for PowerDesigner? I was reading the document of PowerDesigner about how to create an ActiveX Add-in, it says "The ActiveX must implement a specific interface called IPDAddIn to become a PowerDesigner add-in.". But I don't know where the interface IPDAddIn is, and how to implement it ?
Here is the online document
I have this old example, which could give some ideas, even if not everything it up-to-date.
using PdAddInTypLib;
namespace MineSpace
{
[ComVisible(true)]
[Guid("A6FA0D26-77E8-4DD3-B27E-F4050C3D5188")]
public class Launcher : IPdAddIn {
// Main() manages the console or GUI interface
// the PdAddIn interface is managed by an instance of Launcher
[ComVisible(false)]
[STAThread]
public static void Main(String[] args) {
}
public Launcher() {
_app = null;
}
// IPdAddIn implementation
public void Initialize(Object anApplication) {
try {
_app = (PdCommon.Application)anApplication;
}
catch (Exception e) {
// process
}
}
public void Uninitialize() {
}
public String ProvideMenuItems(String aMenu, Object anObj) {
return "";
}
public int IsCommandSupported(String aMenu, Object anObj, String aCommand) {
return 0;
}
public void DoCommand(String aMenu, Object anObj, String aCommand) {
}
private PdCommon.Application _app;
}
}
with the corresponding part in the class declaration:
[HKEY_CLASSES_ROOT\MyPlugin.Launcher]
#="MyPlugin.Launcher"
[HKEY_CLASSES_ROOT\MyPlugin.Launcher\CLSID]
#="{13749EFC-1ADA-4451-8C47-FF0B545FF172}"
[HKEY_CLASSES_ROOT\CLSID\{13749EFC-1ADA-4451-8C47-FF0B545FF172}]
#="MyPlugin.Launcher"
[HKEY_CLASSES_ROOT\CLSID\{13749EFC-1ADA-4451-8C47-FF0B545FF172}\InprocServer32]
#="C:\windows\System32\mscoree.dll"
"ThreadingModel"="Both"
"Class"="MyPlugin.Launcher"
"Assembly"="MyPlugin, Version=1.0.1402.33688, Culture=neutral, PublicKeyToken=null"
"RuntimeVersion"="v1.0.3705"
[HKEY_CLASSES_ROOT\CLSID\{13749EFC-1ADA-4451-8C47-FF0B545FF172}\ProgId]
#="MyPlugin.Launcher"
[HKEY_CLASSES_ROOT\CLSID\{13749EFC-1ADA-4451-8C47-FF0B545FF172}\Implemented Categories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]
And the corresponding code to declare the add-in in PowerDesigner. If the File value is present, PowerDesigner could call DllRegisterServer on it, if the component is not yet registered.
[HKEY_LOCAL_MACHINE\SOFTWARE\Sybase\PowerDesigner 10\Addins\MyPlugin Launcher]
"Enable"="No"
"Class"="MyPlugin.Launcher"
"Type"="ActiveX"
"File"="d:\\myplugin\\myplugin.exe"

Nice code template for windows service

Any links to a good template for a windows service? (looking for C# code)
Something that has the basic functionality that I could extend.
It is a little clear what you are looking for. The Windows Service project type in Visual Studio creates a project with the templates you need to get going with a basic windows service.
You can also look at this article from C# Online. It goes over a few ideas and has a few parts to the article. (Note; the page seems to loads a little slow so be patient)
I use VS2005 and I like to start with the basic template.
Modify the Service class to this
using System;
using System.ServiceProcess;
using System.Timers;
namespace WindowsService1
{
public partial class Service1 : ServiceBase
{
//better is to read from settings or config file
private readonly Double _interval = (new TimeSpan(1, 0, 0, 0)).TotalMilliseconds;
private Timer m_Timer;
public Service1()
{
InitializeComponent();
Init();
}
private void Init()
{
m_Timer = new Timer();
m_Timer.BeginInit();
m_Timer.AutoReset = false;
m_Timer.Enabled = true;
m_Timer.Interval = 1000.0;
m_Timer.Elapsed += m_Timer_Elapsed;
m_Timer.EndInit();
}
private void m_Timer_Elapsed(object sender, ElapsedEventArgs e)
{
//TODO WORK WORK WORK
RestartTimer();
}
private void RestartTimer()
{
m_Timer.Interval = _interval;
m_Timer.Start();
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
Start();
}
protected override void OnStop()
{
Stop();
base.OnStop();
}
public void Start()
{
m_Timer.Start();
}
public new void Stop()
{
m_Timer.Stop();
}
}
}
Install using InstallUtil.exe, after you have added an installer : http://msdn.microsoft.com/en-us/library/ddhy0byf(VS.80).aspx
Keep the Init function small and fast, otherwise your service will not start with an error that the service did not respond in a timely fashion
Hope this helps

Resources