Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
RED TEXT BIG GUN
Sep 1, 2001

Taco Defender

Ithaqua posted:

Oh, and let me mention one of my pet peeves to head it off at the pass, because I see this come up any time IOC comes up: MEF is not an IOC framework.

I know this is a few days old, but would you care to expound on that statement? I'm just reading up on IoC and Dependency Injection since it came up in this thread.

The IoC wikipedia page lists Dependency Injection as a implementation of IoC. The Dependency Injection wikipedia page in turn lists MEF as a implementation. The Ninject project which you mention as a IoC framework has "dependency injection" written all over its site (although their Wiki is having trouble at the moment).

So at first blush without actually having spent time trying to write code with either, it looks like MEF and Ninject are both DI implementations. What's your objection then? That MEF isn't a framework?

Adbot
ADBOT LOVES YOU

RED TEXT BIG GUN
Sep 1, 2001

Taco Defender

Dietrich posted:

Let me quote him on MEF.

That was really helpful! Thanks!

RED TEXT BIG GUN
Sep 1, 2001

Taco Defender
After bumbling through some WPF stuff at work I wanted to get a better grasp on how WPF and MVVM should actually be done. I found this (http://waf.codeplex.com/) and spent a free afternoon looking through it and trying to apply the same sort of concepts to my own code. I finished the day only feeling slightly less lost than before. A few questions:

1. I'm willing to buy a book to get through the learning curve. Any recommendations? I'm more interested in the MVVM, code organization, and threading side of things. I don't want a book that's 70% going through what each WPF control does and how to edit the XAML manually.

2. This is something I'm hoping I can grasp better with a book...

In the couple of small toy programs I wrote I needed to do (thing that takes a while) at program start up. One example was waiting for a process acting as a WCF server to start up and accept my connection. Right now I left this totally synchronous and I'm stalling out the UI. I'm on .NET 4.0 so the await/async discussed a page or two back won't work for me (I think?)

I basically want the UI to pop up as soon as it can and show "Connecting to server..." until I connect without showing hourglasses when I mouse over the window. There seems to be several async options and I think that's what's confusing me. Do I use Task, BackgroundWorker, DispatchTimer, ThreadPool, something else I haven't found yet?

3. Is INotifyPropertyChanged really that terrible or am I missing something entirely?

code:
private string _firstName;

public string FirstName
{
   get { return _firstname; }
   set
   {
      if (_firstname != value)
      {
          _firstname = value;
          OnPropertyChanged("FirstName")
      }
   }
}
For every drat property? And that string that much match the property name? I blew 25 minutes today hunting down a string that I had fat fingered.

RED TEXT BIG GUN
Sep 1, 2001

Taco Defender
Thanks everyone. That helped at lot.

code:
public event EventHandler<EventArgs> SomethingHappened = delegate{};
I will for sure be using that.

The dynamic proxy stuff from this link looks really cool and kind of what I expected a solution to look like.

RED TEXT BIG GUN
Sep 1, 2001

Taco Defender
I am writing some C# code to install unmanaged Windows services.

1. Because I'm installing a service for an arbitrary unmanaged process and not my own managed process, I can't use ServiceInstaller. I'm stuck using pinvokes to the Windows API. If that's wrong please God let me know and I can get rid of all this ugly code.

2. Is there a good resource that goes through (most of) everything you can do with pinvokes? Like a guide that will let me be confident in looking up a unmanaged API and then getting the pinvoke right? I don't have a good understanding at all and have been mostly stumbling through it with guess and check. My experience so far as been copy/pasting from pinvoke.net or blogs and changing random things until it works.

fake edit #1: I found the MSDN docs on it, maybe that's good enough. I did a search in book on Amazon in C# 5.0 unleashed and it looks like it's only mentioned in passing.

3. I wasted most of the afternoon trying to get ChangeServiceConfig2 to work just for SERVICE_CONFIG_DESCRIPTION. This was more complicated than the other pinvoke copy/paste jobs I've done because of the LPVOID struct in the third parameter. I eventually got to this (bunch of code omitted):

code:
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool ChangeServiceConfig2(IntPtr hService, 
    InfoLevel dwInfoLevel, 
    [MarshalAs(UnmanagedType.Struct)] ref SERVICE_DESCRIPTION lpInfo);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct SERVICE_DESCRIPTION
{
    public string description;
}

// Somewhere in some function
SERVICE_DESCRIPTION desc = new SERVICE_DESCRIPTION { description = config.Description };

if (!ChangeServiceConfig2(service, InfoLevel.ServiceConfigDescription, ref desc))
{
    throw new Win32Exception(Marshal.GetLastWin32Error());
}
That worked, but when I tested (I only tested on Win7 64-bit) it was only showing the first character of the description string. This looked like a shoving a Unicode string into a Ansi parameter problem, so I changed StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode) with StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi) and things worked fine.

How was I supposed to know this beforehand? The docs on the SERVICE_DESCRIPTION struct have it as a LPTSTR. CharSet docs say Charset.Unicode should work on Windows versions higher than '98. There is CharSet.Auto, but I just tried that and it (like the docs say) chooses Unicode and you get the same bad result.

fake edit #2: I think I just figured it out, but I'm going to leave the previous text up because I already wrote it out. DllImport docs say CharSet.Ansi is the default, which means ChangeServiceConfig2 in my code would actually be calling ChangeServiceConfig2A, which is Ansi, which means I was shoving a Unicode string into an Ansi parameter.

real questions then: Is there a way I can default my whole project so DllImport has CharSet = CharSet.Auto? Or do I have to set that attribute everywhere I have a [DllImport...]?

(I realize the above code has ChangeServiceConfig2 so it can only change the service description. Tomorrow I'm going to look at making it set the other config settings.)

RED TEXT BIG GUN
Sep 1, 2001

Taco Defender
I have a hard .NET == 4.0 requirement on this WPF project. I'm trying to do the old don't block the UI thread trick. I tried using Tasks and ContinueWith and am running into basically the exact same problem as this guy.

The canExecute() of the ICommand of a Button on my window isn't being called until I click on any other window in the OS. The solution they gave in that thread was to convert the Task into a BackgroundWorker. Is that what I really have to do? I thought Tasks were supposed to supersede (in a way) BackgroundWorkers?

RED TEXT BIG GUN
Sep 1, 2001

Taco Defender

zokie posted:

I've had the same problem, in your AsyncCommand, or whatever, call CommandManager.Invalidateblahblah after you set the isExecuting to false right after the the delegate is done executing. This tells the CommandManager to raise the RequerySuggested event which should tell fix your UI problem.

Ooh cool. I'll try that out when I get home. Thanks!

RED TEXT BIG GUN
Sep 1, 2001

Taco Defender

zokie posted:

I've had the same problem, in your AsyncCommand, or whatever, call CommandManager.Invalidateblahblah after you set the isExecuting to false right after the the delegate is done executing. This tells the CommandManager to raise the RequerySuggested event which should tell fix your UI problem.

This did the trick. Thanks!

RED TEXT BIG GUN
Sep 1, 2001

Taco Defender
What are reasons for a WCF server running on a NetNamedPipeBinding to queue requests?

I have a long running server task that raises events to populate a command queue. It then loops through that queue and executes the commands (custom command class). I'm trying to add a cancel feature. The client sends a Cancel request to the server. That request sets a flag in the server object. Before adding a new command item or, if processing already started, before executing the next command, the long running task checks that flag and cancels out if it's true.

This is mostly working, but depending when I send that Cancel request I'm seeing the long running task take quite a while to cancel out. I added in a bunch of logging. Example log: Client log will show at 00:00:00 Cancel() being called. Server log won't show Cancel() even being received until 00:00:07. Everything works fine once the server actually receives and executes the Cancel request, it's the delay I'm concerned about.

I eventually broke down and had the client launch the long running task and then ping the server every second just to get the server to log out when it receives the ping request. I would expect in the server logs to see one log line about every second, but instead I'm seeing some single requests, chunks of 3-4 requests sporadically, and the biggest chunk is 11 requests coming in at once. That big chunk is 11 seconds of unresponsiveness of my cancel feature.

I have the server set with ConcurrencyMode.Multiple and I do see the ping requests coming in on a different thread than the long running task, which is what I'd expect.

Sorry for the code dump, but it's hard to strip this down to a small amount of code.

Server is self-hosted(?) like this. I added the throttling behavior recently but it didn't have an effect.

C# code:
log.Info("Setting up server.");
var host = new ServiceHost(typeof(Server), pipeUri);
var binding = new NetNamedPipeBinding();
binding.ReceiveTimeout = TimeSpan.MaxValue; // Do not time out waiting for responses from callbacks


host.AddServiceEndpoint(typeof(IServer), binding, "");
host.Description.Behaviors.Add(new ErrorHandlerServiceBehavior());
host.Description.Behaviors.Add(new ServiceThrottlingBehavior
{
    MaxConcurrentSessions = 100,
    MaxConcurrentCalls = 100,
    MaxConcurrentInstances = 100
});

host.Open();
Stripped down Server interface.

C# code:
[ServiceContract(CallbackContract = typeof(IServerCallback))]
public interface IServer
{
    [OperationContract(IsOneWay = true)]
    void DoLongRunningThing();

    [OperationContract(IsOneWay = true)]
    void Cancel();

    [OperationContract(IsOneWay = true)]
    void Ping();
}
Attributes on the Server implementation

C# code:
[ServiceBehavior(
    InstanceContextMode = InstanceContextMode.PerSession, // One object of this class is created per session with a client
    ConcurrencyMode = ConcurrencyMode.Multiple, // That object is multithreaded
    UseSynchronizationContext = false, // Don't use the synchronization context of whatever thread calls .Open()
    IncludeExceptionDetailInFaults = true)]
public class Server : IServer
{
    ...
}
Stripped down callback interface / implementation if it matters.

C# code:
public interface IServerCallback
{
    [OperationContract(IsOneWay = true)]
    void ProgressChanged(string message, int value, int maximum);
}

[CallbackBehavior(
    ConcurrencyMode = ConcurrencyMode.Multiple, 
    UseSynchronizationContext = false)]
public class ServerCallback : IServerCallback
{
    ...
}

Adbot
ADBOT LOVES YOU

RED TEXT BIG GUN
Sep 1, 2001

Taco Defender

Ithaqua posted:

I'm doing something for a client and they want an installer. What's the best/easiest way to do this? Basically, I need to prompt for a database server/name and credentials, then an API key for my client's service. Afterwards, stick the API key in an XML file and run a console application that handles doing some database stuff. I want this to be as straightforward as possible, and WIX looks like it has a learning curve that I don't feel like tackling right now.

I do installers for a living. Your options are:

Windows Installer (MSIs). This is the Way You're Supposed To Do It, but the overall design sucks and probably isn't worth your time. I'll go into details about why it sucks if you want. WiX and InstallShield are two interfaces to making MSIs, but they both create MSIs that feed into Windows Installer. WiX is free, InstallShield is pretty expensive.

ClickOnce. This is terrible and shouldn't really be used for anything outside of deploying some internal app to your coworkers (personal opinion). It doesn't give you an interface for a UI, so it doesn't meet your requirements anyway.

Nullsoft Scriptable Install System. This is a scripting framework for installations. I know Mozilla uses it for Firefox. You can grab the Firefox source and take a look at their NSIS code for a good real-world example. Upside is that it doesn't have any built-in restrictions like Windows Installer. Downside is that it is it's own scripting language that you'll never use outside of writing NSIS installers and may not be able to do everything you want. At my firm I had spent some time looking at this, but we never actually used it so I can't give you personal experience.

Roll your own. This is what my firm is actually paying me to do this year. I'm using C#, which is why I've popped into this thread a few times. The only things you really need to make an executable an installer is to add an entry into Add/Remove Programs (now called Programs and Features) and put some executable on the system that will do the uninstall. If all your app need to do to be installed is to dump some files somewhere, this might actually be the quickest given that you're already proficient in C#. I took a look at the Google Chrome installer and they basically took this route of not using Windows Installer and rolling their own (but with C++). And for what it's worth, I'm pretty sure Steam went a similar route.

Those are the options I'm aware of. I'd be happy to help you out with anything since you've helped me quite a bit just by posting insightful things in this thread. PM me if you want.

  • Locked thread