<?xml version="1.0" encoding="windows-1252"?>
<node id="913943" title="Importing a jpeg into an AD attribute with Win32::OLE" created="2011-07-12 11:53:08" updated="2011-07-12 11:53:08">
<type id="115">
perlquestion</type>
<author id="472157">
bingos</author>
<data>
<field name="doctext">
&lt;p&gt;Hello, I am having trouble with updating the &lt;i&gt;thumbnailPhoto&lt;/i&gt; Active Directory attribute using the ADSI interface through Win32::OLE&lt;/p&gt;

&lt;p&gt;I have been able to add photos using an Active Directory Users and Computers extension to individual user accounts, but I would like to have a way of doing 'bulk' imports. And of course my language of choice is perl for doing this.&lt;/p&gt;

&lt;p&gt;The &lt;i&gt;thumbnailPhoto&lt;/i&gt; attribute is an 'octet string' and I don't believe I've tried to manipulate this type of attribute before, though, I have retrieved values from them without any problems.&lt;/p&gt;

&lt;p&gt;First off, I thought I would try and export images that had been previously imported:&lt;/p&gt;

&lt;code&gt;
use strict;
use warnings;
use Win32::OLE qw[in];

my $adspath = shift || die "Provide an adspath already\n";

{
  warn $adspath, "\n";
  my $user = Win32::OLE-&gt;GetObject("LDAP://$adspath");
  die "Oh dear\n" unless $user;
  $user-&gt;GetInfo;
  unless ( defined $user-&gt;{thumbnailPhoto} ) {
     warn "No thumbnail\n";
     exit 0;
  }
  my $thumb = $user-&gt;{thumbnailPhoto};
  {
    open my $piccy, '&gt;:raw', 'piccy.jpg' or die "$!\n";
    print $piccy $thumb;
  }
}
exit 0;
&lt;/code&gt;

&lt;p&gt;This works fine to retrieve a 'piccy' and I had a JPEG file I could open and admire.&lt;/p&gt;

&lt;p&gt;Buoyed up by the success of this, I tried this:&lt;/p&gt;

&lt;code&gt;
use strict;
use warnings;
use File::Slurp;
use Win32::OLE qw[in];

my $adspath = shift || die "Provide an adspath already\n";

my $filename = shift || die "No filename provided\n";
my $content = read_file( $filename, binmode =&gt; ':raw' );

{
  warn $adspath, "\n";
  my $user = Win32::OLE-&gt;GetObject("LDAP://$adspath");
  die "Oh dear\n" unless $user;
  $user-&gt;GetInfo;
  $user-&gt;Put('thumbnailPhoto',$content);
  $user-&gt;SetInfo;
}
exit 0;
&lt;/code&gt;

&lt;p&gt;This ends up with 'ÿØÿà' in the attribute.&lt;/p&gt;

&lt;p&gt;I tried various things, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Win32::OLE::Variant - Variant( VT_ARRAY|VT_UI1, $content )&lt;/li&gt;
&lt;li&gt;pack and unpack&lt;/li&gt;
&lt;li&gt;Sacrificial slaughter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The above seemed to either have no effect (Variant) or put garbage in the attribute&lt;/p&gt;

&lt;p&gt;I found VBScript code that seemed to use a &lt;i&gt;byte array&lt;/i&gt; to assign to the attribute:&lt;/p&gt;

&lt;code&gt;
Function ReadBinaryFile(FileName)
Const adTypeBinary = 1
Dim BinaryStream
Set BinaryStream = CreateObject("ADODB.Stream")
BinaryStream.Type = adTypeBinary
BinaryStream.Open
BinaryStream.LoadFromFile FileName
ReadBinaryFile = BinaryStream.Read
End Function

Set objNewUser = GetObject("LDAP://cn=some,ou=adspath,dc=domain,dc=local")
objNewUser.GetInfo
objNewUser.Put "thumbnailPhoto", ReadBinaryFile("image.jpg")
objNewUser.SetInfo
&lt;/code&gt;

&lt;p&gt;I have an idea what a byte array is, but not how to coerce one from the contents of a Perl scalar. So I am stuck and would be grateful of any advice.&lt;/p&gt;

&lt;p&gt;Many thanks in advance.&lt;/p&gt;</field>
</data>
</node>
